From c951908bc201afa59402967d50fa926212845fae Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Feb 2012 07:43:30 +0100 Subject: QString: add from{Ascii,Latin1,Utf8,Local8Bit() overloads for QByteArray One of the more frequent uses for QByteArray::operator const char*() is in passing a QByteArray to QString::fromLatin1(). But this is highly inefficient, since the bytearray already knows its size, but since its demoted to a const char* in passing to fromLatin1(), it forces the latter to call strlen() _again_. The solution, then, is to add overloads for QByteArray that pass the array's .size() as a second argument to the two-arg fromLatin1() version. Change-Id: I5ea1ad3c96d9e64167be53c0c418c7b7dba51f68 Reviewed-by: David Faure Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index f1bad5c028..12a5acb689 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -417,6 +417,10 @@ public: { return fromLocal8Bit_helper(str, (str && size == -1) ? int(strlen(str)) : size); } + static inline QString fromAscii(const QByteArray &str) { return fromAscii(str.data(), str.size()); } + static inline QString fromLatin1(const QByteArray &str) { return fromLatin1(str.data(), str.size()); } + static inline QString fromUtf8(const QByteArray &str) { return fromUtf8(str.data(), str.size()); } + static inline QString fromLocal8Bit(const QByteArray &str) { return fromLocal8Bit(str.data(), str.size()); } static QString fromUtf16(const ushort *, int size = -1); static QString fromUcs4(const uint *, int size = -1); static QString fromRawData(const QChar *, int size); -- cgit v1.2.3 From ddf4b378f1e7eac62bd504a1e453cb7b894e21f2 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 25 Feb 2012 12:40:20 +0100 Subject: Inline and mark as deprecated images's serialNumber() These function are marked as obsolete since Qt 4.3 The motivation here was too fix QPixmap::serialNumber which is marked as QT_DEPRECATED_SINCE but was not inlined. But then I took the oportunity to do the same with all the other functions. Change-Id: Ic50a7857461fc402b2f2b4528c83e53e8e28ea30 Reviewed-by: Lars Knoll --- src/gui/image/qimage.cpp | 11 ++--------- src/gui/image/qimage.h | 4 +++- src/gui/image/qpixmap.cpp | 9 ++------- src/gui/image/qpixmap.h | 2 +- src/gui/image/qpixmap_raster.cpp | 4 ++-- src/gui/kernel/qpalette.cpp | 7 ++----- src/gui/kernel/qpalette.h | 4 +++- src/gui/text/qtextcursor.cpp | 2 +- src/widgets/kernel/qicon.cpp | 8 ++------ src/widgets/kernel/qicon.h | 4 +++- .../text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp | 2 +- tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp | 2 +- 12 files changed, 23 insertions(+), 36 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 5b23dbf4dc..23d212cc92 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -5132,7 +5132,8 @@ bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth #undef IWX_LSB #undef IWX_PIX -/*! \obsolete +/*! \fn int QImage::serialNumber() const + \obsolete Returns a number that identifies the contents of this QImage object. Distinct QImage objects can only have the same serial number if they refer to the same contents (but they don't @@ -5147,14 +5148,6 @@ bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth \sa operator==() */ -int QImage::serialNumber() const -{ - if (!d) - return 0; - else - return d->ser_no; -} - /*! Returns a number that identifies the contents of this QImage object. Distinct QImage objects can only have the same key if they diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 5a3ae8f886..e9192f1031 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -253,7 +253,9 @@ public: inline static QImage fromData(const QByteArray &data, const char *format = 0) { return fromData(reinterpret_cast(data.constData()), data.size(), format); } - int serialNumber() const; +#if QT_DEPRECATED_SINCE(5, 0) + QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } +#endif qint64 cacheKey() const; QPaintEngine *paintEngine() const; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index e8c1304b74..1f325f5b6b 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -885,7 +885,8 @@ void QPixmap::fill(const QColor &color) data->fill(color); } -/*! \obsolete +/*! \fn int QPixmap::serialNumber() const + \obsolete Returns a number that identifies the contents of this QPixmap object. Distinct QPixmap objects can only have the same serial number if they refer to the same contents (but they don't have @@ -898,12 +899,6 @@ void QPixmap::fill(const QColor &color) it as a cache key. For caching pixmaps, we recommend using the QPixmapCache class whenever possible. */ -int QPixmap::serialNumber() const -{ - if (isNull()) - return 0; - return data->serialNumber(); -} /*! Returns a number that identifies this QPixmap. Distinct QPixmap diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 27bfe15688..3d78a43917 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -146,7 +146,7 @@ public: void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = 0); #if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED int serialNumber() const; + QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } #endif qint64 cacheKey() const; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 8125b1360d..7c7c4652e3 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -115,7 +115,7 @@ void QRasterPlatformPixmap::resize(int width, int height) image.setColor(1, QColor(Qt::color1).rgba()); } - setSerialNumber(image.serialNumber()); + setSerialNumber(image.cacheKey() >> 32); } bool QRasterPlatformPixmap::fromData(const uchar *buffer, uint len, const char *format, @@ -349,7 +349,7 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC } is_null = (w <= 0 || h <= 0); - setSerialNumber(image.serialNumber()); + setSerialNumber(image.cacheKey() >> 32); } QImage* QRasterPlatformPixmap::buffer() diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index 6d3d1c9580..90d96674bc 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -844,7 +844,8 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) return true; } -/*! \obsolete +/*! \fn int QPalette::serialNumber() const + \obsolete Returns a number that identifies the contents of this QPalette object. Distinct QPalette objects can only have the same serial @@ -860,10 +861,6 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2) \sa operator==() */ -int QPalette::serialNumber() const -{ - return d->ser_no; -} /*! Returns a number that identifies the contents of this QPalette diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index cc710fa67a..ca619a89b4 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -139,7 +139,9 @@ public: inline bool operator!=(const QPalette &p) const { return !(operator==(p)); } bool isCopyOf(const QPalette &p) const; - int serialNumber() const; +#if QT_DEPRECATED_SINCE(5, 0) + QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } +#endif qint64 cacheKey() const; QPalette resolve(const QPalette &) const; diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index ddf2fb080e..cbffc4315f 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -2325,7 +2325,7 @@ void QTextCursor::insertImage(const QImage &image, const QString &name) } QString imageName = name; if (name.isEmpty()) - imageName = QString::number(image.serialNumber()); + imageName = QString::number(image.cacheKey()); d->priv->document()->addResource(QTextDocument::ImageResource, QUrl(imageName), image); QTextImageFormat format; format.setName(imageName); diff --git a/src/widgets/kernel/qicon.cpp b/src/widgets/kernel/qicon.cpp index e579fac4f4..c848dd74f4 100644 --- a/src/widgets/kernel/qicon.cpp +++ b/src/widgets/kernel/qicon.cpp @@ -621,7 +621,8 @@ QIcon::operator QVariant() const return QVariant(QVariant::Icon, this); } -/*! \obsolete +/*! \fn int QIcon::serialNumber() const + \obsolete Returns a number that identifies the contents of this QIcon object. Distinct QIcon objects can have @@ -638,11 +639,6 @@ QIcon::operator QVariant() const \sa QPixmap::serialNumber() */ -int QIcon::serialNumber() const -{ - return d ? d->serialNum : 0; -} - /*! Returns a number that identifies the contents of this QIcon object. Distinct QIcon objects can have the same key if diff --git a/src/widgets/kernel/qicon.h b/src/widgets/kernel/qicon.h index 7bef500946..c6e07ba3e2 100644 --- a/src/widgets/kernel/qicon.h +++ b/src/widgets/kernel/qicon.h @@ -94,7 +94,9 @@ public: bool isDetached() const; void detach(); - int serialNumber() const; +#if QT_DEPRECATED_SINCE(5, 0) + QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } +#endif qint64 cacheKey() const; void addPixmap(const QPixmap &pixmap, Mode mode = Normal, State state = Off); diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp index 50ae22c530..7ca4fc981b 100644 --- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp +++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp @@ -2938,7 +2938,7 @@ void tst_QTextDocumentFragment::backgroundImage() doc.setHtml("

Hello

"); QBrush bg = doc.begin().blockFormat().background(); QVERIFY(bg.style() == Qt::TexturePattern); - QVERIFY(bg.texture().serialNumber() == doc.testPixmap.serialNumber()); + QCOMPARE(bg.texture().cacheKey(), doc.testPixmap.cacheKey()); } void tst_QTextDocumentFragment::dontMergePreAndNonPre() diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 907a239912..7cc043e247 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -1333,7 +1333,7 @@ void tst_QComboBox::textpixmapdata() for (int i = 0; iitemIcon(i); - QVERIFY(icon.serialNumber() == icons.at(i).serialNumber()); + QCOMPARE(icon.cacheKey(), icons.at(i).cacheKey()); QPixmap original = icons.at(i).pixmap(1024); QPixmap pixmap = icon.pixmap(1024); QVERIFY(pixmap.toImage() == original.toImage()); -- cgit v1.2.3 From 8397a44bedf542b53284674c87268819f4911d31 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 22 Feb 2012 16:17:30 +0100 Subject: QByteArray: deprecate QT_NO_CAST_FROM_BYTEARRAY-protected operators The QByteArray::operator const {char,void}*() implicit conversions are a source of subtle bugs, so they right- fully can be disabled with QT_NO_CAST_FROM_BYTEARRAY. const char *d = qstring.toLatin1(); // implicit conversion while ( d ) // oops: d points to freed memory // ... But almost no-one ever enabled this macros in the wild and many were bitten by these implicit conversions, so this patch deprecates them. I would have liked to remove them completely, but there are just too many occurrences even in Qt itself to hope to find all conditionally-compiled code that uses these. Also fixes all code that needs to compile under QT_NO_DEPRECATED (in qmake/, src/tools/). I984706452db7d0841620a0f64e179906123f3849 separately deals with the bulk of changes in src/ and examples/. Depends on I5ea1ad3c96d9e64167be53c0c418c7b7dba51f68. Change-Id: I8d47e6c293c80f61c6288c9f8d42fda41afe2267 Reviewed-by: David Faure Reviewed-by: Lars Knoll --- qmake/generators/integrity/gbuild.cpp | 4 ++-- qmake/generators/mac/pbuilder_pbx.cpp | 2 +- qmake/generators/makefiledeps.cpp | 4 ++-- qmake/generators/win32/msvc_objectmodel.cpp | 2 +- qmake/generators/win32/msvc_objectmodel.h | 2 +- qmake/project.cpp | 10 +++++----- src/corelib/codecs/qtextcodec.cpp | 6 +++--- src/corelib/io/qfilesystemengine_unix.cpp | 18 +++++++++--------- src/corelib/io/qsettings.cpp | 6 +++--- src/corelib/kernel/qvariant.cpp | 2 +- src/corelib/tools/qbytearray.cpp | 6 ++++-- src/corelib/tools/qbytearray.h | 12 ++++-------- src/corelib/tools/qlocale_unix.cpp | 2 +- src/corelib/tools/qstring.cpp | 2 +- src/tools/rcc/rcc.cpp | 2 +- src/tools/uic/cpp/cppwriteicondata.cpp | 4 ++-- src/xml/dom/qdom.cpp | 8 ++++---- src/xml/sax/qxml.cpp | 6 +++--- 18 files changed, 48 insertions(+), 50 deletions(-) diff --git a/qmake/generators/integrity/gbuild.cpp b/qmake/generators/integrity/gbuild.cpp index c72c120f39..895df24193 100644 --- a/qmake/generators/integrity/gbuild.cpp +++ b/qmake/generators/integrity/gbuild.cpp @@ -213,7 +213,7 @@ GBuildMakefileGenerator::write() dllbase += DLLOFFSET; } - warn_msg(WarnParser, Option::output.fileName().toAscii()); + warn_msg(WarnParser, Option::output.fileName().toAscii().constData()); QTextStream t(&Option::output); QString primaryTarget(project->values("QMAKE_CXX").at(0)); @@ -425,7 +425,7 @@ GBuildMakefileGenerator::openOutput(QFile &file, const QString &build) const outputName += QDir::separator(); outputName += fileInfo(project->projectFile()).baseName(); outputName += projectSuffix(); - warn_msg(WarnParser, outputName.toAscii()); + warn_msg(WarnParser, outputName.toAscii().constData()); file.setFileName(outputName); } debug_msg(1, "file is %s", file.fileName().toLatin1().constData()); diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index b78ebd136d..2f6b30fe12 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1374,7 +1374,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } tmp = project->values("QMAKE_PBX_VARS"); for(int i = 0; i < tmp.count(); i++) { - QString var = tmp[i], val = qgetenv(var.toLatin1()); + QString var = tmp[i], val = QString::fromAscii(qgetenv(var.toLatin1().constData())); if(val.isEmpty() && var == "TB") val = "/usr/bin/"; t << "\t\t\t\t" << writeSettings(var, escapeFilePath(val)) << ";" << "\n"; diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index d28d48b4d0..642dd97e68 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -185,9 +185,9 @@ SourceFile *SourceFiles::lookupFile(const char *file) void SourceFiles::addFile(SourceFile *p, const char *k, bool own_file) { - QByteArray ba = p->file.local().toLatin1(); + const QByteArray ba = p->file.local().toLatin1(); if(!k) - k = ba; + k = ba.constData(); int h = hash(k) % num_nodes; SourceFileNode *pn = new SourceFileNode; pn->own_file = own_file; diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 81f541f94e..e0f55a64c9 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -1615,7 +1615,7 @@ bool VCLinkerTool::parseOption(const char* option) { // Split up in subsystem, and version number QStringList both = QString(option+11).split(","); - switch (elfHash(both[0].toLatin1())) { + switch (elfHash(both[0].toLatin1().constData())) { case 0x8438445: // CONSOLE SubSystem = subSystemConsole; break; diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index 8b1cf519ff..37d923f9c1 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -477,7 +477,7 @@ protected: public: void parseOptions(QStringList& options) { for (QStringList::ConstIterator it=options.begin(); (it!=options.end()); it++) - parseOption((*it).toLatin1()); + parseOption((*it).toLatin1().constData()); } static QStringList fixCommandLine(const QString &input); }; diff --git a/qmake/project.cpp b/qmake/project.cpp index 2029e068ec..379854ed6a 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1520,7 +1520,7 @@ QMakeProject::resolveSpec(QString *spec, const QString &qmakespec) if (*spec == "default") { #ifdef Q_OS_UNIX char buffer[1024]; - int l = readlink(qmakespec.toLatin1(), buffer, 1023); + int l = readlink(qmakespec.toLatin1().constData(), buffer, 1023); if (l != -1) { buffer[l] = '\0'; *spec = QString::fromLatin1(buffer); @@ -2070,7 +2070,7 @@ QMakeProject::doProjectExpand(QString func, QList args_list, if(args.count() > 1) singleLine = (args[1].toLower() == "true"); QString output; - FILE *proc = QT_POPEN(args[0].toLatin1(), "r"); + FILE *proc = QT_POPEN(args[0].toLatin1().constData(), "r"); while(proc && !feof(proc)) { int read_in = int(fread(buff, 1, 255, proc)); if(!read_in) @@ -3150,12 +3150,12 @@ QStringList &QMakeProject::values(const QString &_var, QHash 0; oldslash = slash) { - QByteArray chunk = QFile::encodeName(dirName.left(slash)); + const QByteArray chunk = QFile::encodeName(dirName.left(slash)); QT_STATBUF st; - if (QT_STAT(chunk, &st) != -1) { + if (QT_STAT(chunk.constData(), &st) != -1) { if ((st.st_mode & S_IFMT) != S_IFDIR) return false; - if (::rmdir(chunk) != 0) + if (::rmdir(chunk.constData()) != 0) return oldslash != 0; } else { return false; @@ -515,7 +515,7 @@ bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool remo } return true; } - return rmdir(QFile::encodeName(entry.filePath())) == 0; + return rmdir(QFile::encodeName(entry.filePath()).constData()) == 0; } //static @@ -623,7 +623,7 @@ QString QFileSystemEngine::tempPath() bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path) { int r; - r = QT_CHDIR(path.nativeFilePath()); + r = QT_CHDIR(path.nativeFilePath().constData()); return r >= 0; } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 2021c42c4d..f743c592bd 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1752,10 +1752,10 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data, iniSection = iniSection.trimmed(); - if (qstricmp(iniSection, "general") == 0) { + if (qstricmp(iniSection.constData(), "general") == 0) { currentSection.clear(); } else { - if (qstricmp(iniSection, "%general") == 0) { + if (qstricmp(iniSection.constData(), "%general") == 0) { currentSection = QLatin1String(iniSection.constData() + 1); } else { currentSection.clear(); @@ -1912,7 +1912,7 @@ bool QConfFileSettingsPrivate::writeIniFile(QIODevice &device, const ParsedSetti if (realSection.isEmpty()) { realSection = "[General]"; - } else if (qstricmp(realSection, "general") == 0) { + } else if (qstricmp(realSection.constData(), "general") == 0) { realSection = "[%General]"; } else { realSection.prepend('['); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 4e7fd94141..2f67ae9287 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1698,7 +1698,7 @@ void QVariant::load(QDataStream &s) if (typeId == QVariant::UserType) { QByteArray name; s >> name; - typeId = QMetaType::type(name); + typeId = QMetaType::type(name.constData()); if (!typeId) { s.setStatus(QDataStream::ReadCorruptData); return; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index c74c61999d..1d37f578b8 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -343,7 +343,7 @@ int qstrcmp(const QByteArray &str1, const QByteArray &str2) { int l1 = str1.length(); int l2 = str2.length(); - int ret = memcmp(str1, str2, qMin(l1, l2)); + int ret = memcmp(str1.constData(), str2.constData(), qMin(l1, l2)); if (ret != 0) return ret; @@ -995,6 +995,8 @@ QByteArray &QByteArray::operator=(const char *str) /*! \fn QByteArray::operator const char *() const \fn QByteArray::operator const void *() const + \obsolete Use constData() instead. + Returns a pointer to the data stored in the byte array. The pointer can be used to access the bytes that compose the array. The data is '\\0'-terminated. The pointer remains valid as long @@ -2751,7 +2753,7 @@ QDataStream &operator<<(QDataStream &out, const QByteArray &ba) out << (quint32)0xffffffff; return out; } - return out.writeBytes(ba, ba.size()); + return out.writeBytes(ba.constData(), ba.size()); } /*! \relates QByteArray diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 8202097da5..09c43988fd 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -207,8 +207,10 @@ public: void squeeze(); #ifndef QT_NO_CAST_FROM_BYTEARRAY - operator const char *() const; - operator const void *() const; +#if QT_DEPRECATED_SINCE(5, 0) + QT_DEPRECATED operator const char *() const { return constData(); } + QT_DEPRECATED operator const void *() const { return constData(); } +#endif #endif char *data(); const char *data() const; @@ -415,12 +417,6 @@ inline char QByteArray::operator[](uint i) const inline bool QByteArray::isEmpty() const { return d->size == 0; } -#ifndef QT_NO_CAST_FROM_BYTEARRAY -inline QByteArray::operator const char *() const -{ return d->data(); } -inline QByteArray::operator const void *() const -{ return d->data(); } -#endif inline char *QByteArray::data() { detach(); return d->data(); } inline const char *QByteArray::data() const diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp index 6ace96f771..f2876912b4 100644 --- a/src/corelib/tools/qlocale_unix.cpp +++ b/src/corelib/tools/qlocale_unix.cpp @@ -98,7 +98,7 @@ QLocale QSystemLocale::fallbackLocale() const lang = qgetenv("LC_NUMERIC"); if (lang.isEmpty()) lang = qgetenv("LANG"); - return QLocale(QLatin1String(lang)); + return QLocale(QString::fromLatin1(lang)); } QVariant QSystemLocale::query(QueryType type, QVariant in) const diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 704545667c..14b8782dae 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4761,7 +4761,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, } // else fall through # endif // declared in - int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2)); + int delta = strcoll(toLocal8Bit_helper(data1, length1).constData(), toLocal8Bit_helper(data2, length2).constData()); if (delta == 0) delta = ucstrcmp(data1, length1, data2, length2); return delta; diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 5fbda35fc6..bfb3206778 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -681,7 +681,7 @@ bool RCCResourceLibrary::output(QIODevice &outDevice, QIODevice &errorDevice) m_errorDevice->write("Could not write footer\n"); return false; } - outDevice.write(m_out, m_out.size()); + outDevice.write(m_out.constData(), m_out.size()); return true; } diff --git a/src/tools/uic/cpp/cppwriteicondata.cpp b/src/tools/uic/cpp/cppwriteicondata.cpp index 39ce52f4b3..082961cfe6 100644 --- a/src/tools/uic/cpp/cppwriteicondata.cpp +++ b/src/tools/uic/cpp/cppwriteicondata.cpp @@ -176,8 +176,8 @@ void WriteIconData::writeImage(QTextStream &output, const QString &indent, void WriteIconData::writeImage(QIODevice &output, DomImage *image) { - QByteArray array = transformImageData(image->elementData()->text()); - output.write(array, array.size()); + const QByteArray array = transformImageData(image->elementData()->text()); + output.write(array.constData(), array.size()); } } // namespace CPP diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index c16fd03613..38a44024aa 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -5682,24 +5682,24 @@ static QByteArray encodeEntity(const QByteArray& str) QByteArray tmp(str); int len = tmp.size(); int i = 0; - const char* d = tmp.data(); + const char* d = tmp.constData(); while (i < len) { if (d[i] == '%'){ tmp.replace(i, 1, "<"); - d = tmp; + d = tmp.constData(); len += 4; i += 5; } else if (d[i] == '"') { tmp.replace(i, 1, """); - d = tmp; + d = tmp.constData(); len += 4; i += 5; } else if (d[i] == '&' && i + 1 < len && d[i+1] == '#') { // Dont encode < or " or &custom;. // Only encode character references tmp.replace(i, 1, "&"); - d = tmp; + d = tmp.constData(); len += 4; i += 5; } else { diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 2a41ce3426..75e2fdb2e7 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -1612,7 +1612,7 @@ QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning) d->encMapper = codec->makeDecoder(); } - QString input = d->encMapper->toUnicode(data, data.size()); + QString input = d->encMapper->toUnicode(data.constData(), data.size()); if (d->lookingForEncodingDecl) { d->encodingDeclChars += input; @@ -1633,9 +1633,9 @@ QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning) input.clear(); // prime the decoder with the data so far - d->encMapper->toUnicode(d->encodingDeclBytes, d->encodingDeclBytes.size()); + d->encMapper->toUnicode(d->encodingDeclBytes.constData(), d->encodingDeclBytes.size()); // now feed it the new data - input = d->encMapper->toUnicode(data, data.size()); + input = d->encMapper->toUnicode(data.constData(), data.size()); } } } -- cgit v1.2.3 From 3ec9aac6c9aa627eb41f8603c517c8cf71be0af0 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Feb 2012 22:15:57 +0100 Subject: QXmlStream{Reader,Writer}: add explicit to constructors Change-Id: Ib70b7a8f15aaf2e59deddcb0b89eb7e976893280 Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart --- src/corelib/xml/qxmlstream.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h index 3a9ddfd990..90382c7fe5 100644 --- a/src/corelib/xml/qxmlstream.h +++ b/src/corelib/xml/qxmlstream.h @@ -248,10 +248,10 @@ public: QXmlStreamReader(); - QXmlStreamReader(QIODevice *device); - QXmlStreamReader(const QByteArray &data); - QXmlStreamReader(const QString &data); - QXmlStreamReader(const char * data); + explicit QXmlStreamReader(QIODevice *device); + explicit QXmlStreamReader(const QByteArray &data); + explicit QXmlStreamReader(const QString &data); + explicit QXmlStreamReader(const char * data); ~QXmlStreamReader(); void setDevice(QIODevice *device); @@ -361,9 +361,9 @@ class Q_CORE_EXPORT QXmlStreamWriter QDOC_PROPERTY(int autoFormattingIndent READ autoFormattingIndent WRITE setAutoFormattingIndent) public: QXmlStreamWriter(); - QXmlStreamWriter(QIODevice *device); - QXmlStreamWriter(QByteArray *array); - QXmlStreamWriter(QString *string); + explicit QXmlStreamWriter(QIODevice *device); + explicit QXmlStreamWriter(QByteArray *array); + explicit QXmlStreamWriter(QString *string); ~QXmlStreamWriter(); void setDevice(QIODevice *device); -- cgit v1.2.3 From 4550f0db210258338c8d6261640d9f192c0d3db6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Feb 2012 22:39:20 +0100 Subject: QStringMatcher: make constructor explicit Change-Id: I3a8f37d2132eb84bef336afed60aff6e2350366d Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart --- src/corelib/tools/qstringmatcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h index a9b2a7c371..3f614f732c 100644 --- a/src/corelib/tools/qstringmatcher.h +++ b/src/corelib/tools/qstringmatcher.h @@ -55,7 +55,7 @@ class Q_CORE_EXPORT QStringMatcher { public: QStringMatcher(); - QStringMatcher(const QString &pattern, + explicit QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive); QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs = Qt::CaseSensitive); -- cgit v1.2.3 From 5bb1408927b4eb5a03e8ab9f7cbc68f80d8a3962 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Thu, 23 Feb 2012 11:12:58 +1000 Subject: Allow moc to handle symbols that have been redefined. Allow moc to produce the desired identifiers when used with C++ symbol names that have been redefined, for example by -Dfoo=bar. Two changes are required: firstly, when encoding a type name, the components of the name must be checked for substitutions that have been defined for that token (note that this is not done here by correct pre-processing, but only by processing the resultant table of definitions). Secondly, the arguments to the SIGNAL, SLOT and METHOD macros must be allowed to be substituted during macro expansion rather than stringized directly. This is a temporary change to prevent breaking existing projects that depend on the declarative module. After clients have had an opportunity to update their code to the use the new interfaces, it can be removed. Task-number: QTBUG-23737 Change-Id: I39e6844cebf6ca7984af6028160b8a3797ac44a5 Reviewed-by: Martin Jones --- src/corelib/kernel/qobjectdefs.h | 12 ++-- src/tools/moc/main.cpp | 2 +- src/tools/moc/moc.cpp | 110 +++++++++++++++++++++++++++- src/tools/moc/moc.h | 13 +++- tests/auto/tools/moc/tst_moc.cpp | 152 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 278 insertions(+), 11 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 0b1fa8839f..45ef8ab3ca 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -208,16 +208,16 @@ Q_CORE_EXPORT const char *qFlagLocation(const char *method); #ifndef QT_NO_DEBUG # define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__) # ifndef QT_NO_KEYWORDS -# define METHOD(a) qFlagLocation("0"#a QLOCATION) +# define METHOD(a) qFlagLocation("0" QTOSTRING(a) QLOCATION) # endif -# define SLOT(a) qFlagLocation("1"#a QLOCATION) -# define SIGNAL(a) qFlagLocation("2"#a QLOCATION) +# define SLOT(a) qFlagLocation("1" QTOSTRING(a) QLOCATION) +# define SIGNAL(a) qFlagLocation("2" QTOSTRING(a) QLOCATION) #else # ifndef QT_NO_KEYWORDS -# define METHOD(a) "0"#a +# define METHOD(a) "0" QTOSTRING(a) # endif -# define SLOT(a) "1"#a -# define SIGNAL(a) "2"#a +# define SLOT(a) "1" QTOSTRING(a) +# define SIGNAL(a) "2" QTOSTRING(a) #endif #define QMETHOD_CODE 0 // member type codes diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp index 772df1feec..6f67a7dddf 100644 --- a/src/tools/moc/main.cpp +++ b/src/tools/moc/main.cpp @@ -159,7 +159,7 @@ int runMoc(int _argc, char **_argv) bool autoInclude = true; bool defaultInclude = true; Preprocessor pp; - Moc moc; + Moc moc(pp); pp.macros["Q_MOC_RUN"]; pp.macros["__cplusplus"]; QByteArray filename; diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7b358c1ae8..4189c29de1 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -304,7 +304,9 @@ void Moc::parseFunctionArguments(FunctionDef *def) arg.rightType += lexem(); } arg.normalizedType = normalizeType(QByteArray(arg.type.name + ' ' + arg.rightType)); + arg.normalizedType = getTypeSubstitution(arg.normalizedType); arg.typeNameForCast = normalizeType(QByteArray(noRef(arg.type.name) + "(*)" + arg.rightType)); + arg.typeNameForCast = getTypeSubstitution(arg.typeNameForCast); if (test(EQ)) arg.isDefault = true; def->arguments += arg; @@ -414,6 +416,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) } def->normalizedType = normalizeType(def->type.name); + def->normalizedType = getTypeSubstitution(def->normalizedType); if (!test(RPAREN)) { parseFunctionArguments(def); @@ -512,6 +515,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) } def->normalizedType = normalizeType(def->type.name); + def->normalizedType = getTypeSubstitution(def->normalizedType); if (!test(RPAREN)) { parseFunctionArguments(def); @@ -968,6 +972,7 @@ void Moc::createPropertyDef(PropertyDef &propDef) QVariant. */ type = normalizeType(type); + type = getTypeSubstitution(type); if (type == "QMap") type = "QMap"; else if (type == "QValueList") @@ -1081,7 +1086,6 @@ void Moc::parseProperty(ClassDef *def) createPropertyDef(propDef); next(RPAREN); - if(!propDef.notify.isEmpty()) def->notifyableProperties++; if (propDef.revision > 0) @@ -1244,7 +1248,8 @@ void Moc::parseInterfaces(ClassDef *def) } // resolve from classnames to interface ids for (int i = 0; i < iface.count(); ++i) { - const QByteArray iid = interface2IdMap.value(iface.at(i).className); + QByteArray className = getTypeSubstitution(iface.at(i).className); + QByteArray iid = interface2IdMap.value(className); if (iid.isEmpty()) error("Undefined interface"); @@ -1502,6 +1507,107 @@ void Moc::checkProperties(ClassDef *cdef) } } +QByteArray Moc::getSubstitution(const QByteArray &token) const +{ + Macros::ConstIterator it = preprocessor.macros.find(token); + if (it != preprocessor.macros.end() && it->symbols.count() == 1) { + // We can only handle substitutions that result in a single symbol + return it->symbols.at(0).lexem(); + } + + return QByteArray(); +} + +QByteArray Moc::getTokenSubstitution(const QByteArray &token) const +{ + QByteArray result = token; + + QSet used; + + // Process substitution chain until no replacement exists + QByteArray substitution = getSubstitution(result); + while (!substitution.isEmpty()) { + used.insert(result); + result = substitution; + + if (used.contains(result)) { + break; + } + + substitution = getSubstitution(result); + } + + return result; +} + +QByteArray Moc::getWordSubstitution(const QByteArray &word) const +{ + QByteArray result; + + // A word can contain multiple components separated by '*' + int startIndex = 0; + do { + int index = word.indexOf('*', startIndex); + if (index == -1) { + result.append(getTokenSubstitution(word.mid(startIndex))); + } else { + result.append(getTokenSubstitution(word.mid(startIndex, (index - startIndex)))); + result.append('*'); + } + + startIndex = index + 1; + } while (startIndex != 0); + + return result; +} + +QByteArray Moc::getNameSubstitution(const QByteArray &name) const +{ + QByteArray result; + + // Parse multiple tokens in this name independently + int startIndex = 0; + do { + int index = name.indexOf(' ', startIndex); + if (index == -1) { + result.append(getWordSubstitution(name.mid(startIndex))); + } else { + result.append(getWordSubstitution(name.mid(startIndex, (index - startIndex)))); + result.append(' '); + } + + startIndex = index + 1; + } while (startIndex != 0); + + return result; +} + +QByteArray Moc::getTypeSubstitution(const QByteArray &typeName) const +{ + int index = typeName.indexOf('<'); + if (index != -1) { + QByteArray templateName = typeName.left(index); + + int lastIndex = typeName.lastIndexOf('>'); + if (lastIndex > index) { + QByteArray result = getNameSubstitution(templateName); + + // Parse the interior type independently + QByteArray parameter = typeName.mid(index + 1, (lastIndex - index - 1)); + QByteArray interior = getTypeSubstitution(parameter); + if (interior.endsWith('>')) { + interior.append(' '); + } + result.append('<').append(interior).append(typeName.mid(lastIndex)); + return result; + } else { + // Something is broken; return the input unmodified + return typeName; + } + } + + return getNameSubstitution(typeName); +} QT_END_NAMESPACE diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index aedb97b234..9e9225da0a 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -43,6 +43,7 @@ #define MOC_H #include "parser.h" +#include "preprocessor.h" #include #include #include @@ -197,12 +198,14 @@ struct NamespaceDef { class Moc : public Parser { public: - Moc() - : noInclude(false), generatedCode(false), mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false) + Moc(Preprocessor &p) + : preprocessor(p), noInclude(false), generatedCode(false), + mustIncludeQMetaTypeH(false), mustIncludeQPluginH(false) {} QByteArray filename; + Preprocessor &preprocessor; bool noInclude; bool generatedCode; bool mustIncludeQMetaTypeH; @@ -260,6 +263,12 @@ public: void checkSuperClasses(ClassDef *def); void checkProperties(ClassDef* cdef); + + QByteArray getSubstitution(const QByteArray &token) const; + QByteArray getTokenSubstitution(const QByteArray &token) const; + QByteArray getWordSubstitution(const QByteArray &word) const; + QByteArray getNameSubstitution(const QByteArray &name) const; + QByteArray getTypeSubstitution(const QByteArray &typeName) const; }; inline QByteArray noRef(const QByteArray &type) diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 27db6cc59c..49095048bf 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -535,6 +535,7 @@ private slots: void cxx11Enums_data(); void cxx11Enums(); void returnRefs(); + void redefinedNames(); signals: void sigWithUnsignedArg(unsigned foo); @@ -1762,6 +1763,157 @@ void tst_Moc::returnRefs() // they used to cause miscompilation of the moc generated file. } +struct ActualInterfaceName +{ + virtual ~ActualInterfaceName() {} + virtual void foo() = 0; +}; + +QT_BEGIN_NAMESPACE +Q_DECLARE_INTERFACE(ActualInterfaceName, "foo.bar.ActualInterfaceName") +QT_END_NAMESPACE + +#define DefinedInterfaceName ActualInterfaceName +#define RedefinedInterfaceName DefinedInterfaceName + +struct ActualName {}; +#define DefinedName ActualName +#define RedefinedName DefinedName + +template +struct ActualTemplateName {}; + +#define DefinedTemplateName ActualTemplateName +#define RedefinedTemplateName DefinedTemplateName + +#define ActualName ActualName + +class RedefinitionTest : public QObject, public RedefinedInterfaceName +{ + Q_OBJECT + Q_INTERFACES(RedefinedInterfaceName) + + Q_PROPERTY(ActualName p1 READ getP1) + + Q_PROPERTY(DefinedName p2 READ getP2) + Q_PROPERTY(RedefinedName p3 READ getP3) + + Q_PROPERTY(DefinedName * p4 READ getP4) + Q_PROPERTY(RedefinedName * p5 READ getP5) + + Q_PROPERTY(DefinedName ** p6 READ getP6) + Q_PROPERTY(RedefinedName ** p7 READ getP7) + + Q_PROPERTY(DefinedName const ** p8 READ getP8) + Q_PROPERTY(RedefinedName const ** p9 READ getP9) + + Q_PROPERTY(DefinedName const * const * p10 READ getP10) + Q_PROPERTY(RedefinedName const * const * p11 READ getP11) + + Q_PROPERTY(DefinedTemplateName p16 READ getP16) + Q_PROPERTY(RedefinedTemplateName p17 READ getP17) + + Q_PROPERTY(DefinedTemplateName p18 READ getP18) + Q_PROPERTY(RedefinedTemplateName p19 READ getP19) + + Q_PROPERTY(DefinedTemplateName p20 READ getP20) + Q_PROPERTY(RedefinedTemplateName p21 READ getP21) + +signals: + void signal1(ActualName); + void signal2(DefinedName); + void signal3(RedefinedName); + +public slots: + void slot1(ActualName x) { v = x; } + void slot2(DefinedName x) { v = x; } + void slot3(RedefinedName x) { v = x; } + +public: + void foo() {} + + ActualName v; + + ActualName *vp; + ActualName const *vcp; + + ActualTemplateName tv; + ActualTemplateName tvpp; + ActualTemplateName tvcpc; + + ActualName getP0() { return v; } + ActualName getP1() { return v; } + + DefinedName getP2() { return v; } + RedefinedName getP3() { return v; } + + DefinedName * getP4() { return &v; } + RedefinedName * getP5() { return &v; } + + DefinedName ** getP6() { return &vp; } + RedefinedName ** getP7() { return &vp; } + + DefinedName const ** getP8() { return &vcp; } + RedefinedName const ** getP9() { return &vcp; } + + DefinedName const * const * getP10() const { return &vcp; } + RedefinedName const * const * getP11() const { return &vcp; } + + DefinedTemplateName getP16() { return tv; } + RedefinedTemplateName getP17() { return tv; } + + DefinedTemplateName getP18() { return tvpp; } + RedefinedTemplateName getP19() { return tvpp; } + + DefinedTemplateName getP20() { return tvcpc; } + RedefinedTemplateName getP21() { return tvcpc; } +}; + +void tst_Moc::redefinedNames() +{ + RedefinitionTest tst; + const QMetaObject *mobj = tst.metaObject(); + QVERIFY(mobj->indexOfProperty("p1") != -1); + + // Use the true slot name rather than the declared name + QVERIFY(QObject::connect(&tst, SIGNAL(signal1(ActualName)), + &tst, SLOT(slot1(ActualName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal2(ActualName)), + &tst, SLOT(slot2(ActualName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal3(ActualName)), + &tst, SLOT(slot3(ActualName)))); + + // Use the declared slot name rather than the true name + QVERIFY(QObject::connect(&tst, SIGNAL(signal1(ActualName)), + &tst, SLOT(slot2(DefinedName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal1(ActualName)), + &tst, SLOT(slot3(RedefinedName)))); + + // Use the declared signal name rather than the true name + QVERIFY(QObject::connect(&tst, SIGNAL(signal2(DefinedName)), + &tst, SLOT(slot1(ActualName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal3(RedefinedName)), + &tst, SLOT(slot1(ActualName)))); + + // Use both declared names + QVERIFY(QObject::connect(&tst, SIGNAL(signal2(DefinedName)), + &tst, SLOT(slot2(DefinedName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal2(DefinedName)), + &tst, SLOT(slot3(RedefinedName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal3(RedefinedName)), + &tst, SLOT(slot2(DefinedName)))); + + QVERIFY(QObject::connect(&tst, SIGNAL(signal3(RedefinedName)), + &tst, SLOT(slot3(RedefinedName)))); +} + + QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" -- cgit v1.2.3 From 6225e3ba01ef918724a15dd1311ab5d8205be534 Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Thu, 23 Feb 2012 11:31:05 +1000 Subject: Add workaround for projects using 'QT += declarative' The code previously exported by the declarative library has been migrated to the qml and quick libraries, and the symbol names have been changed accordingly. To allow existing projects to continue to build, the declarative module now contains a set of definitions redefining the deprecated class names to their replacement names. To make this work, a dependency on the declarative module now automatically adds a dependency on the qml module in order to make the new library available for linking. This is a temporary change to prevent breaking existing projects that depend on the declarative module. After clients have had an opportunity to update their code to the use the new interfaces, it can be removed. Task-number: QTBUG-23737 Change-Id: Idee6ac627858856802bb1be29e9a4a079da73688 Reviewed-by: Kent Hansen Reviewed-by: Lars Knoll Reviewed-by: Martin Jones --- mkspecs/features/qt.prf | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index b7da02e5bb..1c2aec49c6 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -1,5 +1,32 @@ CONFIG *= moc thread +# Temporary fixes to avoid QDeclarative -> QQml breakage: + +# Projects depending on declarative will now get the full set of +# -DOldSymbol=NewSymbol definitions added to their configuration +# so that the old symbol names still compile. All code previously +# in the declarative library is now in the qml library. +contains(QT, qmldevtools):!contains(QT, declarative) { + QT += declarative +} +contains(QT, qmldevtools-private):!contains(QT, declarative-private) { + QT += declarative-private +} + +contains(QT, quick):!contains(QT, declarative) { + QT += declarative +} +contains(QT, quick-private):!contains(QT, declarative-private) { + QT += declarative-private +} + +contains(QT, declarative):!contains(QT, qml) { + QT += qml +} +contains(QT, declarative-private):!contains(QT, qml-private) { + QT += qml-private +} + #handle defines win32 { qt_static:DEFINES += QT_NODLL -- cgit v1.2.3 From 643fd1afdd4b83641e08cc8db04b17416d835121 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 26 Feb 2012 11:53:56 +0100 Subject: QFontEngine: remove unused and buggy grayPalette() QFontEngine::grayPalette() mistakenly returns an empty vector, so even if there's a user (the class it exported, after all), it cannot correctly use it. So, just remove it. Change-Id: Id5f70139e5f6ed9a2a3f28400cd0750d14cb7dc0 Reviewed-by: Olivier Goffart Reviewed-by: Jiang Jiang --- src/gui/text/qfontengine.cpp | 19 ------------------- src/gui/text/qfontengine_p.h | 1 - 2 files changed, 20 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index a084a3dd8c..4bceb28ef7 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1148,25 +1148,6 @@ QByteArray QFontEngine::convertToPostscriptFontFamilyName(const QByteArray &fami return f; } -class QRgbGreyPalette: public QVector -{ -public: - QRgbGreyPalette() - { - resize(256); - QRgb *it = data(); - for (int i = 0; i < size(); ++i, ++it) - *it = 0xff000000 | i | (i<<8) | (i<<16); - } -}; - -Q_GLOBAL_STATIC(QVector, qt_grayPalette) - -const QVector &QFontEngine::grayPalette() -{ - return *qt_grayPalette(); -} - QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) { if (glyphs.numGlyphs >= 1) { diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 023882d560..cf9c26f2a4 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -278,7 +278,6 @@ public: int m_subPixelPositionCount; // Number of positions within a single pixel for this cache protected: - static const QVector &grayPalette(); QFixed lastRightBearing(const QGlyphLayout &glyphs, bool round = false); private: -- cgit v1.2.3 From 67ac8d72d5288c77540ed0db3039695ff533b002 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 25 Feb 2012 13:56:11 +0100 Subject: QTestlib: no need to use the preprocessor to distinguish qreal The code paths are actually the same, so merge them. Change-Id: I456b8a9a825cccdd80cd6a52a0a6737cde252363 Reviewed-by: Jason McDonald --- src/testlib/qtestcase.h | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index e4f4020461..c64420b000 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -264,38 +264,20 @@ namespace QTest template bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int); -#if defined(QT_COORD_TYPE) && (defined(Q_PROCESSOR_ARM) || defined(QT_NO_FPU) || defined(Q_OS_WINCE)) template <> - inline bool qCompare(qreal const &t1, float const &t2, const char *actual, + inline bool qCompare(double const &t1, float const &t2, const char *actual, const char *expected, const char *file, int line) { - return qCompare(t1, qreal(t2), actual, expected, file, line); + return qCompare(qreal(t1), qreal(t2), actual, expected, file, line); } template <> - inline bool qCompare(float const &t1, qreal const &t2, const char *actual, + inline bool qCompare(float const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) { - return qCompare(qreal(t1), t2, actual, expected, file, line); + return qCompare(qreal(t1), qreal(t2), actual, expected, file, line); } -#elif defined(QT_COORD_TYPE) || defined(Q_PROCESSOR_ARM) || defined(QT_NO_FPU) || defined(Q_OS_WINCE) - template <> - inline bool qCompare(qreal const &t1, double const &t2, const char *actual, - const char *expected, const char *file, int line) - { - return qCompare(float(t1), float(t2), actual, expected, file, line); - } - - template <> - inline bool qCompare(double const &t1, qreal const &t2, const char *actual, - const char *expected, const char *file, int line) - { - return qCompare(float(t1), float(t2), actual, expected, file, line); - } - -#endif - template inline bool qCompare(const T *t1, const T *t2, const char *actual, const char *expected, const char *file, int line) -- cgit v1.2.3 From c06e932c7307530d23d218ef7ed86bc06583f2d1 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 25 Feb 2012 17:00:15 +0100 Subject: Move the QString comparison operator as non member function The operator== and similar should not be member of the class. This ensure a symertry. Indeed, consider this code string == string1 + string2; string1 + string2 == string; The first line compile fine even if QStringBuilder is used, because QStringBuilder will be converted to QString implicitly. But the second line do not compile if the operator== is a member of QString, because the implicit conversion rules do not apply. For this reason, the symetric operators should not be declared as member. Change-Id: I3f7c11fab45a9133f7a424bdfcb894f97da9282b Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.cpp | 44 ++++++++++++++++++++++++------------------- src/corelib/tools/qstring.h | 12 ++++++------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 14b8782dae..d0c5506228 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2139,7 +2139,8 @@ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivi /*! - Returns true if string \a other is equal to this string; otherwise + \relates QString + Returns true if string \a s1 is equal to string \a s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values of @@ -2147,12 +2148,12 @@ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivi expect. Consider sorting user-interface strings with localeAwareCompare(). */ -bool QString::operator==(const QString &other) const +bool operator==(const QString &s1, const QString &s2) { - if (d->size != other.d->size) + if (s1.d->size != s2.d->size) return false; - return qMemEquals(d->data(), other.d->data(), d->size); + return qMemEquals(s1.d->data(), s2.d->data(), s1.d->size); } /*! @@ -2207,17 +2208,18 @@ bool QString::operator==(const QLatin1String &other) const */ /*! - Returns true if this string is lexically less than string \a - other; otherwise returns false. + \relates QString + Returns true if string \a s1 is lexically less than string + \a s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values of the characters and is very fast, but is not what a human would expect. Consider sorting user-interface strings using the QString::localeAwareCompare() function. */ -bool QString::operator<(const QString &other) const +bool operator<(const QString &s1, const QString &s2) { - return ucstrcmp(constData(), length(), other.constData(), other.length()) < 0; + return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0; } /*! @@ -2268,10 +2270,11 @@ bool QString::operator<(const QLatin1String &other) const go through QObject::tr(), for example. */ -/*! \fn bool QString::operator<=(const QString &other) const +/*! \fn bool operator<=(const QString &s1, const QString &s2) + \relates QString - Returns true if this string is lexically less than or equal to - string \a other; otherwise returns false. + Returns true if string \a s1 is lexically less than or equal to + string \a s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values of the characters and is very fast, but is not what a human would @@ -2311,10 +2314,11 @@ bool QString::operator<(const QLatin1String &other) const go through QObject::tr(), for example. */ -/*! \fn bool QString::operator>(const QString &other) const +/*! \fn bool operator>(const QString &s1, const QString &s2) + \relates QString - Returns true if this string is lexically greater than string \a - other; otherwise returns false. + Returns true if string \a s1 is lexically greater than string \a + s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values of the characters and is very fast, but is not what a human would @@ -2370,10 +2374,11 @@ bool QString::operator>(const QLatin1String &other) const for example. */ -/*! \fn bool QString::operator>=(const QString &other) const +/*! \fn bool operator>=(const QString &s1, const QString &s2) + \relates QString - Returns true if this string is lexically greater than or equal to - string \a other; otherwise returns false. + Returns true if string \a s1 is lexically greater than or equal to + string \a s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values of the characters and is very fast, but is not what a human would @@ -2413,9 +2418,10 @@ bool QString::operator>(const QLatin1String &other) const for example. */ -/*! \fn bool QString::operator!=(const QString &other) const +/*! \fn bool operator!=(const QString &s1, const QString &s2) + \relates QString - Returns true if this string is not equal to string \a other; + Returns true if string \a s1 is not equal to string \a s2; otherwise returns false. The comparison is based exclusively on the numeric Unicode values diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 12a5acb689..bdadba8bd4 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -486,12 +486,12 @@ public: static QString number(qulonglong, int base=10); static QString number(double, char f='g', int prec=6); - bool operator==(const QString &s) const; - bool operator<(const QString &s) const; - inline bool operator>(const QString &s) const { return s < *this; } - inline bool operator!=(const QString &s) const { return !operator==(s); } - inline bool operator<=(const QString &s) const { return !operator>(s); } - inline bool operator>=(const QString &s) const { return !operator<(s); } + friend Q_CORE_EXPORT bool operator==(const QString &s1, const QString &s2); + friend Q_CORE_EXPORT bool operator<(const QString &s1, const QString &s2); + friend inline bool operator>(const QString &s1, const QString &s2) { return s2 < s1; } + friend inline bool operator!=(const QString &s1, const QString &s2) { return !(s1 == s2); } + friend inline bool operator<=(const QString &s1, const QString &s2) { return !(s1 > s2); } + friend inline bool operator>=(const QString &s1, const QString &s2) { return !(s1 < s2); } bool operator==(const QLatin1String &s) const; bool operator<(const QLatin1String &s) const; -- cgit v1.2.3 From f79768cd39a58529656b320bfaa9c096eccb191d Mon Sep 17 00:00:00 2001 From: Matthew Vogt Date: Fri, 24 Feb 2012 10:51:42 +1000 Subject: Remove Q_DECLARATIVE_EXPORT and Q_QTQUICK1_EXPORT Theses definitions are no longer required in qtbase. Task-number: QTBUG-23737 Change-Id: Ib11e5840086b44120adabe83a1b068c991920f2f Reviewed-by: Martin Jones Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 1fb5778f14..fb6eaeb452 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -610,16 +610,6 @@ class QDataStream; # else # define Q_SVG_EXPORT Q_DECL_IMPORT # endif -# if defined(QT_BUILD_QTQUICK1_LIB) -# define Q_QTQUICK1_EXPORT Q_DECL_EXPORT -# else -# define Q_QTQUICK1_EXPORT Q_DECL_IMPORT -# endif -# if defined(QT_BUILD_DECLARATIVE_LIB) -# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT -# else -# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT -# endif # if defined(QT_BUILD_OPENGL_LIB) # define Q_OPENGL_EXPORT Q_DECL_EXPORT # else @@ -680,8 +670,6 @@ class QDataStream; # define Q_SQL_EXPORT Q_DECL_IMPORT # define Q_NETWORK_EXPORT Q_DECL_IMPORT # define Q_SVG_EXPORT Q_DECL_IMPORT -# define Q_DECLARATIVE_EXPORT Q_DECL_IMPORT -# define Q_QTQUICK1_EXPORT Q_DECL_IMPORT # define Q_CANVAS_EXPORT Q_DECL_IMPORT # define Q_OPENGL_EXPORT Q_DECL_IMPORT # define Q_MULTIMEDIA_EXPORT Q_DECL_IMPORT @@ -714,8 +702,6 @@ class QDataStream; # define Q_SQL_EXPORT Q_DECL_EXPORT # define Q_NETWORK_EXPORT Q_DECL_EXPORT # define Q_SVG_EXPORT Q_DECL_EXPORT -# define Q_DECLARATIVE_EXPORT Q_DECL_EXPORT -# define Q_QTQUICK1_EXPORT Q_DECL_EXPORT # define Q_OPENGL_EXPORT Q_DECL_EXPORT # define Q_MULTIMEDIA_EXPORT Q_DECL_EXPORT # define Q_OPENVG_EXPORT Q_DECL_EXPORT @@ -734,8 +720,6 @@ class QDataStream; # define Q_SQL_EXPORT # define Q_NETWORK_EXPORT # define Q_SVG_EXPORT -# define Q_DECLARATIVE_EXPORT -# define Q_QTQUICK1_EXPORT # define Q_OPENGL_EXPORT # define Q_MULTIMEDIA_EXPORT # define Q_OPENVG_EXPORT -- cgit v1.2.3 From 6c1bdc1854a7700c2b3a345b95f6a2fdca84037d Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 23 Feb 2012 22:40:01 +0100 Subject: QFontMetrics: make conversion from QFont to QFontMetrics explicit There is no user of this in qtbase, and I don't think this is a desireable feature anyway. Change-Id: Ifebba5872b0eadb0daba3c3cd5f8b19abeed5c12 Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart --- src/gui/text/qfontmetrics.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 7ddc8975e4..e48460ffd0 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -61,7 +61,7 @@ class QRect; class Q_GUI_EXPORT QFontMetrics { public: - QFontMetrics(const QFont &); + explicit QFontMetrics(const QFont &); QFontMetrics(const QFont &, QPaintDevice *pd); QFontMetrics(const QFontMetrics &); ~QFontMetrics(); @@ -127,7 +127,7 @@ private: class Q_GUI_EXPORT QFontMetricsF { public: - QFontMetricsF(const QFont &); + explicit QFontMetricsF(const QFont &); QFontMetricsF(const QFont &, QPaintDevice *pd); QFontMetricsF(const QFontMetrics &); QFontMetricsF(const QFontMetricsF &); -- cgit v1.2.3 From e05d5c36beb1116657e87d0088ee6153115f320a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 24 Feb 2012 20:32:08 +0100 Subject: factor out code to install default mkspec Change-Id: I15f371df7bc24cd85c1c0924d1929da4dc3db16d Reviewed-by: Joerg Bornemann Reviewed-by: Bradley T. Hughes Reviewed-by: Marius Storm-Olsen --- tools/configure/configureapp.cpp | 41 +++++++++++++++++++++++----------------- tools/configure/configureapp.h | 1 + 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index b7eeea6b60..36c9501d5a 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2638,6 +2638,29 @@ QString Configure::addDefine(QString def) } #if !defined(EVAL) +bool Configure::copySpec(const char *name, const char *pfx, const QString &spec) +{ + // Copy configured mkspec to default directory, but remove the old one first, if there is any + QString defSpec = buildPath + "/mkspecs/" + name; + QFileInfo defSpecInfo(defSpec); + if (defSpecInfo.exists()) { + if (!Environment::rmdir(defSpec)) { + cout << "Couldn't update default " << pfx << "mkspec! Are files in " << qPrintable(defSpec) << " read-only?" << endl; + dictionary["DONE"] = "error"; + return false; + } + } + + QString pltSpec = sourcePath + "/mkspecs/" + spec; + QString includeSpec = buildPath + "/mkspecs/" + spec; + if (!Environment::cpdir(pltSpec, defSpec, includeSpec)) { + cout << "Couldn't update default " << pfx << "mkspec! Does " << qPrintable(pltSpec) << " exist?" << endl; + dictionary["DONE"] = "error"; + return false; + } + return true; +} + void Configure::generateConfigfiles() { QDir(buildPath).mkpath("src/corelib/global"); @@ -2821,25 +2844,9 @@ void Configure::generateConfigfiles() tmpFile.close(); } - // Copy configured mkspec to default directory, but remove the old one first, if there is any - QString defSpec = buildPath + "/mkspecs/default"; - QFileInfo defSpecInfo(defSpec); - if (defSpecInfo.exists()) { - if (!Environment::rmdir(defSpec)) { - cout << "Couldn't update default mkspec! Are files in " << qPrintable(defSpec) << " read-only?" << endl; - dictionary["DONE"] = "error"; - return; - } - } - QString spec = dictionary.contains("XQMAKESPEC") ? dictionary["XQMAKESPEC"] : dictionary["QMAKESPEC"]; - QString pltSpec = sourcePath + "/mkspecs/" + spec; - QString includeSpec = buildPath + "/mkspecs/" + spec; - if (!Environment::cpdir(pltSpec, defSpec, includeSpec)) { - cout << "Couldn't update default mkspec! Does " << qPrintable(pltSpec) << " exist?" << endl; - dictionary["DONE"] = "error"; + if (!copySpec("default", "", spec)) return; - } // Generate the new qconfig.cpp file QDir(buildPath).mkpath("src/corelib/global"); diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index c3838fb139..58544b5041 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -79,6 +79,7 @@ public: void generateMakefiles(); void appendMakeItem(int inList, const QString &item); #if !defined(EVAL) + bool copySpec(const char *name, const char *pfx, const QString &spec); void generateConfigfiles(); #endif void showSummary(); -- cgit v1.2.3 From 65b42dd4c8e6aed6ad84dbd4063da3961a779433 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Feb 2012 17:16:03 +0100 Subject: look for mkspecs in the project root, not next to every project qmake would look for mkspecs/ in the directory containing the current project file. this makes completely no sense with recursive projects: a) nobody would make per-project specs and b) specs meant to be global would not be found. consequently, we look for a project root when starting qmake and use only that directory. if .qmake.cache is found/set, we assume that to be the project root. otherwise, we search for mkspecs/ the same way we search for the cache - just to up until we find one or hit the root. if we are shadow-building, search the build dir as well. Change-Id: Ie66b189a40c21203d956e681cbef44a89f98cd17 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/main.cpp | 2 +- qmake/option.cpp | 31 ++++++++++++++++++++++++++++++- qmake/option.h | 3 ++- qmake/project.cpp | 9 +++------ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/qmake/main.cpp b/qmake/main.cpp index 54cf9f9bdf..985afaa8e8 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -163,7 +163,7 @@ int runQMake(int argc, char **argv) fn = fn.right(fn.length() - di - 1); } - if (!Option::prepareProject()) { + if (!Option::prepareProject(fn)) { exit_val = 3; break; } diff --git a/qmake/option.cpp b/qmake/option.cpp index 0c649fdd77..16c5390348 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -116,6 +116,7 @@ bool Option::mkfile::do_dep_heuristics = true; bool Option::mkfile::do_preprocess = false; bool Option::mkfile::do_stub_makefile = false; bool Option::mkfile::do_cache = true; +QString Option::mkfile::project_root; QString Option::mkfile::project_build_root; QString Option::mkfile::cachefile; QStringList Option::mkfile::project_files; @@ -576,7 +577,7 @@ void Option::applyHostMode() } } -bool Option::prepareProject() +bool Option::prepareProject(const QString &pfile) { mkfile::project_build_root.clear(); if (mkfile::do_cache) { @@ -601,6 +602,34 @@ bool Option::prepareProject() } } no_cache: + + QString srcpath = (pfile != "-") + ? QDir::cleanPath(QFileInfo(pfile).absolutePath()) : qmake_getpwd(); + if (srcpath != output_dir || mkfile::project_build_root.isEmpty()) { + QDir srcdir(srcpath); + QDir dstdir(output_dir); + do { + if (!mkfile::project_build_root.isEmpty()) { + // If we already know the build root, just match up the source root with it. + if (dstdir.path() == mkfile::project_build_root) { + mkfile::project_root = srcdir.path(); + break; + } + } else { + // Look for mkspecs/ in source and build. First to win determines the root. + if (dstdir.exists("mkspecs") || srcdir.exists("mkspecs")) { + mkfile::project_build_root = dstdir.path(); + mkfile::project_root = srcdir.path(); + if (mkfile::project_root == mkfile::project_build_root) + mkfile::project_root.clear(); + break; + } + } + } while (!srcdir.isRoot() && srcdir.cdUp() && !dstdir.isRoot() && dstdir.cdUp()); + } else { + mkfile::project_root.clear(); + } + return true; } diff --git a/qmake/option.h b/qmake/option.h index b8a3b561fa..a4d8cccbec 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -108,7 +108,7 @@ struct Option //both of these must be called.. static int init(int argc=0, char **argv=0); //parse cmdline static void applyHostMode(); - static bool prepareProject(); + static bool prepareProject(const QString &pfile); static bool postProcessProject(QMakeProject *); enum StringFixFlags { @@ -202,6 +202,7 @@ struct Option static bool do_dep_heuristics; static bool do_preprocess; static bool do_stub_makefile; + static QString project_root; static QString project_build_root; static QString cachefile; static int cachefile_depth; diff --git a/qmake/project.cpp b/qmake/project.cpp index 1179812b1b..0e0ac93c5a 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -607,6 +607,9 @@ QStringList qmake_mkspec_paths() for(QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) ret << ((*it) + concat); } + ret << Option::mkfile::project_build_root + concat; + if (!Option::mkfile::project_root.isEmpty()) + ret << Option::mkfile::project_root + concat; ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; return ret; @@ -1307,11 +1310,6 @@ QMakeProject::read(uchar cmd) } if(QDir::isRelativePath(qmakespec)) { - if (QFile::exists(Option::output_dir+"/"+qmakespec+"/qmake.conf")) { - qmakespec = Option::mkfile::qmakespec = QFileInfo(Option::output_dir+"/"+qmakespec).absoluteFilePath(); - } else if (QFile::exists(qmakespec+"/qmake.conf")) { - Option::mkfile::qmakespec = QFileInfo(Option::mkfile::qmakespec).absoluteFilePath(); - } else { bool found_mkspec = false; for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QLatin1Char('/') + qmakespec; @@ -1326,7 +1324,6 @@ QMakeProject::read(uchar cmd) qmakespec.toLatin1().constData(), mkspec_roots.join("\n\t").toLatin1().constData()); return false; } - } } // parse qmake configuration -- cgit v1.2.3 From 672e5a4e883cd894d0e2a0e058d8f8d9a8d87746 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 21 Feb 2012 21:50:29 +0100 Subject: don't abuse $$fromfile() for inspecting entire projects a project can rightfully expect a sane environment. $$fromfile() does not necessarily provide that. so instead use include() with a target namespace. Change-Id: I8d6d30ab1b760d4930c9b4453bc92f8f8ad0b0ae Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- src/src.pro | 4 ++-- src/tools/tools.pro | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/src.pro b/src/src.pro index 6e1517fb07..941064eb59 100644 --- a/src/src.pro +++ b/src/src.pro @@ -90,8 +90,8 @@ for(subname, SRC_SUBDIRS) { subdir = $$replace(subdir, $$reg_src, $$QT_BUILD_TREE) subdir = $$replace(subdir, /, $$QMAKE_DIR_SEP) subdir = $$replace(subdir, \\\\, $$QMAKE_DIR_SEP) - SUB_TEMPLATE = $$fromfile($$subpro, TEMPLATE) - !isEqual(subname, src_tools_bootstrap):if(isEqual(SUB_TEMPLATE, lib) | isEqual(SUB_TEMPLATE, subdirs)):!separate_debug_info { + include($$subpro, SUB) + !isEqual(subname, src_tools_bootstrap):if(isEqual(SUB.TEMPLATE, lib) | isEqual(SUB.TEMPLATE, subdirs)):!separate_debug_info { #debug debug-$${subtarget}.depends = $${subdir}$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_DEBUG_TARGETS debug-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) debug) diff --git a/src/tools/tools.pro b/src/tools/tools.pro index cf10163539..082339cac9 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -32,8 +32,8 @@ for(subname, TOOLS_SUBDIRS) { subdir = $$replace(subdir, $$reg_src, $$QT_BUILD_TREE) subdir = $$replace(subdir, /, $$QMAKE_DIR_SEP) subdir = $$replace(subdir, \\\\, $$QMAKE_DIR_SEP) - SUB_TEMPLATE = $$fromfile($$subpro, TEMPLATE) - !isEqual(subname, src_tools_bootstrap):if(isEqual(SUB_TEMPLATE, lib) | isEqual(SUB_TEMPLATE, subdirs)):!separate_debug_info { + include($$subpro, SUB) + !isEqual(subname, src_tools_bootstrap):if(isEqual(SUB.TEMPLATE, lib) | isEqual(SUB.TEMPLATE, subdirs)):!separate_debug_info { #debug debug-$${subtarget}.depends = $${subdir}$${QMAKE_DIR_SEP}$(MAKEFILE) $$EXTRA_DEBUG_TARGETS debug-$${subtarget}.commands = (cd $$subdir && $(MAKE) -f $(MAKEFILE) debug) -- cgit v1.2.3 From 78faefdbb1ccc296c967dde40e2a7a1c78e4cec2 Mon Sep 17 00:00:00 2001 From: Hib Eris Date: Wed, 8 Feb 2012 13:36:28 +0100 Subject: Implement missing replacements when installing .pc files for win32 This implements replacements for win32 makefile generators similar to the replacement functionality in unix makefile generators. To enable Makefile code generation for replacements in win32 makefile generators, you must set QMAKE_STREAM_EDITOR to e.g. sed. When building for win32, sed is normally only available in the mingw/msys build environment and when cross compiling on unix. In these cases QMAKE_STREAM_EDITOR is set to sed in qmake.conf. For other win32 build environments QMAKE_STREAM_EDITOR is not set in qmake.conf and the replacements Makefile code is not generated. Change-Id: Ie5de5d517eafaeaa2544f1e972aec3fe11d0a6f1 Reviewed-by: Oswald Buddenhagen --- mkspecs/unsupported/win32-g++-cross/qmake.conf | 1 + mkspecs/win32-g++/qmake.conf | 1 + qmake/generators/win32/winmakefile.cpp | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mkspecs/unsupported/win32-g++-cross/qmake.conf b/mkspecs/unsupported/win32-g++-cross/qmake.conf index 7f41c8aab3..9dcff807fa 100644 --- a/mkspecs/unsupported/win32-g++-cross/qmake.conf +++ b/mkspecs/unsupported/win32-g++-cross/qmake.conf @@ -79,6 +79,7 @@ QMAKE_SH = bash MINGW_IN_SHELL = 1 QMAKE_DIR_SEP = / QMAKE_COPY = cp +QMAKE_STREAM_EDITOR = sed QMAKE_COPY_DIR = cp -R QMAKE_MOVE = mv QMAKE_DEL_FILE = rm -f diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index c1f0ac3307..641e4109ff 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -79,6 +79,7 @@ QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain QMAKE_DIR_SEP = / QMAKE_QMAKE ~= s,\\\\,/, QMAKE_COPY = cp + QMAKE_STREAM_EDITOR = sed QMAKE_COPY_DIR = cp -r QMAKE_MOVE = mv QMAKE_DEL_FILE = rm diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index a26be16f78..9d983ffc66 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -649,6 +649,7 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) t << "DEF_FILE = " << varList("DEF_FILE") << endl; t << "RES_FILE = " << varList("RES_FILE") << endl; // Not on mingw, can't see why not though... t << "COPY = " << var("QMAKE_COPY") << endl; + t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl; t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; @@ -852,7 +853,22 @@ QString Win32MakefileGenerator::defaultInstall(const QString &t) } if(!ret.isEmpty()) ret += "\n\t"; - ret += "-$(INSTALL_FILE) \"" + pkgConfigFileName(true) + "\" \"" + dst_pc + "\""; + const QString replace_rule("QMAKE_PKGCONFIG_INSTALL_REPLACE"); + if (project->isEmpty(replace_rule) + || project->isActiveConfig("no_sed_meta_install") + || project->isEmpty("QMAKE_STREAM_EDITOR")) { + ret += "-$(INSTALL_FILE) \"" + pkgConfigFileName(true) + "\" \"" + dst_pc + "\""; + } else { + ret += "-$(SED)"; + QStringList replace_rules = project->values(replace_rule); + for (int r = 0; r < replace_rules.size(); ++r) { + const QString match = project->first(replace_rules.at(r) + ".match"), + replace = project->first(replace_rules.at(r) + ".replace"); + if (!match.isEmpty() /*&& match != replace*/) + ret += " -e \"s," + match + "," + replace + ",g\""; + } + ret += " \"" + pkgConfigFileName(true) + "\" >\"" + dst_pc + "\""; + } if(!uninst.isEmpty()) uninst.append("\n\t"); uninst.append("-$(DEL_FILE) \"" + dst_pc + "\""); -- cgit v1.2.3 From 4a82f78dea36c297b5a4a44853936cc733de8197 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 22:06:36 +0100 Subject: QPair: remove user-defined copy assignment operator The compiler-generated copy assignment operator is fine, and the user-defined one prevents the compiler from synthesising a move assignment operator. Change-Id: I044104a2fd4d7522a910d5c2a68d11dabeca99c4 Reviewed-by: Olivier Goffart --- src/corelib/tools/qpair.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 501f2af3e6..064a75048c 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -57,9 +57,7 @@ struct QPair QPair() : first(T1()), second(T2()) {} QPair(const T1 &t1, const T2 &t2) : first(t1), second(t2) {} - - QPair &operator=(const QPair &other) - { first = other.first; second = other.second; return *this; } + // compiler-generated copy/move ctor/assignment operators are fine! T1 first; T2 second; -- cgit v1.2.3 From 525d98725b72984e3d2526415829b763fc7654ea Mon Sep 17 00:00:00 2001 From: Hib Eris Date: Wed, 8 Feb 2012 16:13:42 +0100 Subject: De-duplicate platform-dependent paths Change-Id: Ifee9f05fc8d924877f24edfddb0dc5e324a29080 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_module_config.prf | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/mkspecs/features/qt_module_config.prf b/mkspecs/features/qt_module_config.prf index a8439198df..4bec33cfd1 100644 --- a/mkspecs/features/qt_module_config.prf +++ b/mkspecs/features/qt_module_config.prf @@ -116,14 +116,18 @@ embedded:DEPENDPATH += ;$$EMBEDDED_H #install directives load(qt_installs) -unix { - CONFIG += create_libtool create_pc explicitlib - QMAKE_LIBTOOL_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PRL_LIBDIR = $$[QT_INSTALL_LIBS] +unix|win32-g++* { + CONFIG += create_pc QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] QMAKE_PKGCONFIG_DESTDIR = pkgconfig +} + +unix { + CONFIG += create_libtool explicitlib + QMAKE_LIBTOOL_LIBDIR = $$[QT_INSTALL_LIBS] + QMAKE_PRL_LIBDIR = $$[QT_INSTALL_LIBS] include_replace.match = $$QMAKE_INCDIR_QT include_replace.replace = $$[QT_INSTALL_HEADERS] lib_replace.match = $$QMAKE_LIBDIR_QT @@ -135,14 +139,6 @@ unix { QMAKE_PKGCONFIG_INSTALL_REPLACE += include_replace lib_replace prefix_replace } -win32-g++* { - CONFIG += create_pc - QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET - QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] - QMAKE_PKGCONFIG_DESTDIR = pkgconfig -} - contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE DEFINES *= QT_NO_CAST_TO_ASCII QT_ASCII_CAST_WARNINGS DEFINES *= QT_MOC_COMPAT #we don't need warnings from calling moc code in our generated code -- cgit v1.2.3 From b72bcea864e6e38f14c8f0c94b7ea6019d7d8a01 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 22:09:48 +0100 Subject: QPair: don't copy-initialise 'first'/'second' in the default ctor Why would we want copy-initialisation if we can have the default constructor? Change-Id: Id2de36d42ef9f63793ff4e3ec36202d3f2bf5f30 Reviewed-by: Olivier Goffart --- src/corelib/tools/qpair.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 064a75048c..5df33a4e9d 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -55,7 +55,7 @@ struct QPair typedef T1 first_type; typedef T2 second_type; - QPair() : first(T1()), second(T2()) {} + QPair() : first(), second() {} QPair(const T1 &t1, const T2 &t2) : first(t1), second(t2) {} // compiler-generated copy/move ctor/assignment operators are fine! -- cgit v1.2.3 From 1e3015d8f4c5b3c04e412dfa8f87def0922c52d9 Mon Sep 17 00:00:00 2001 From: Hib Eris Date: Wed, 8 Feb 2012 13:52:01 +0100 Subject: Activate replacements when installing .pc files for win32 Change-Id: Iaacbe8528bdbe1c1fca60ae8c94625e951f14554 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_module_config.prf | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mkspecs/features/qt_module_config.prf b/mkspecs/features/qt_module_config.prf index 4bec33cfd1..e106c3f1e7 100644 --- a/mkspecs/features/qt_module_config.prf +++ b/mkspecs/features/qt_module_config.prf @@ -122,21 +122,21 @@ unix|win32-g++* { QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] QMAKE_PKGCONFIG_DESTDIR = pkgconfig -} - -unix { - CONFIG += create_libtool explicitlib - QMAKE_LIBTOOL_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PRL_LIBDIR = $$[QT_INSTALL_LIBS] include_replace.match = $$QMAKE_INCDIR_QT include_replace.replace = $$[QT_INSTALL_HEADERS] lib_replace.match = $$QMAKE_LIBDIR_QT lib_replace.replace = $$[QT_INSTALL_LIBS] prefix_replace.match = $$QT_BUILD_TREE prefix_replace.replace = $$[QT_INSTALL_PREFIX] + QMAKE_PKGCONFIG_INSTALL_REPLACE += include_replace lib_replace prefix_replace +} + +unix { + CONFIG += create_libtool explicitlib + QMAKE_LIBTOOL_LIBDIR = $$[QT_INSTALL_LIBS] + QMAKE_PRL_LIBDIR = $$[QT_INSTALL_LIBS] QMAKE_PRL_INSTALL_REPLACE += include_replace lib_replace QMAKE_LIBTOOL_INSTALL_REPLACE += include_replace lib_replace - QMAKE_PKGCONFIG_INSTALL_REPLACE += include_replace lib_replace prefix_replace } contains(QT_PRODUCT, OpenSource.*):DEFINES *= QT_OPENSOURCE -- cgit v1.2.3 From aac821c220662ec9d1acbf88ac82603bbda3cee8 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 22:52:41 +0100 Subject: QRingBuffer: make constructor explicit This is a private class, but it's so close to the classical Stack(int) example for explicit that I just have to make this ctor explicit, too: QRingBuffer rb = 0; // oops: meant '*rb' now no longer compiles. Change-Id: I7d58c1f08c1b14d14930426159c5c8db71b4cf4d Reviewed-by: Olivier Goffart --- src/corelib/tools/qringbuffer_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index 46e505099a..c248477f2c 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QRingBuffer { public: - inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) { + explicit inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) { buffers << QByteArray(); clear(); } -- cgit v1.2.3 From 6363672163a8d40c685c0120f76b261685ee34be Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 22 Feb 2012 16:36:52 +0100 Subject: Add support for QT_NO_SIGNALS_SLOTS_KEYWORDS QT_NO_KEYWORDS can be used for example to ensure that foreach can not be used, but Q_FOREACH must be, that slots must not be used but Q_SLOTS must be, etc. Typically they are used to avoid symbol conflict with other libraries that may use the same keywords (I think boost uses signals). For 3rd party libraries, it makes sense to use Q_SLOTS and Q_SIGNALS instead of slots and signals, so that downstreams can still choose to use QT_NO_KEYWORDS in their code. The most convenient way to enforce that currently is to define QT_NO_KEYWORDS when building the 3rd party library. However, that has the inconvenient side effect of making foreach, forever and emit not usable within the library implementation. This patch makes it possible for the 3rd party library to use QT_NO_SIGNALS_SLOTS_KEYWORDS to exclude signals and slots without affecting whether the other keywords can be used in the library implementation. Change-Id: If1e16a4fa384bd3a2ddd737143499f8b587bc4f8 Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- src/corelib/kernel/qobjectdefs.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index ec51251531..15daf223b9 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -65,8 +65,10 @@ class QString; # if defined(QT_NO_KEYWORDS) # define QT_NO_EMIT # else -# define slots -# define signals public +# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS +# define slots +# define signals public +# endif # endif # define Q_SLOTS # define Q_SIGNALS public -- cgit v1.2.3 From e500946de964649b03fa9d73dd98e58a973bc956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lund=20Martsum?= Date: Mon, 27 Feb 2012 10:56:42 +0100 Subject: QHeaderView - remove sectionCount variable A previous patch ensures that we have exactly one section in a Span. ( see SHA : b800d8b94a7861ecf8853621f6556fca186fb5b7 ) Therefore we no longer need the sectionCount variable. We have assess to it through the sectionSpan.count. To keep this patch quite simple the variable sectionCount has been changed to a function returning the count value. Change-Id: Ibc419eafa38ab64b08f93074cb6ae4b8518995f6 Reviewed-by: Stephen Kelly --- src/widgets/itemviews/qheaderview.cpp | 116 +++++++++++++++++----------------- src/widgets/itemviews/qheaderview_p.h | 20 +++--- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 5d2aceaade..eac543d37d 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -490,7 +490,7 @@ void QHeaderView::setOffset(int newOffset) void QHeaderView::setOffsetToSectionPosition(int visualSectionNumber) { Q_D(QHeaderView); - if (visualSectionNumber > -1 && visualSectionNumber < d->sectionCount) { + if (visualSectionNumber > -1 && visualSectionNumber < d->sectionCount()) { int position = d->headerSectionPosition(d->adjustedVisualIndex(visualSectionNumber)); setOffset(position); } @@ -597,7 +597,7 @@ int QHeaderView::visualIndexAt(int position) const int vposition = position; d->executePostedLayout(); d->executePostedResize(); - const int count = d->sectionCount; + const int count = d->sectionCount(); if (count < 1) return -1; @@ -728,7 +728,7 @@ void QHeaderView::moveSection(int from, int to) Q_D(QHeaderView); d->executePostedLayout(); - if (from < 0 || from >= d->sectionCount || to < 0 || to >= d->sectionCount) + if (from < 0 || from >= d->sectionCount() || to < 0 || to >= d->sectionCount()) return; if (from == to) { @@ -828,7 +828,7 @@ void QHeaderView::swapSections(int first, int second) if (first == second) return; d->executePostedLayout(); - if (first < 0 || first >= d->sectionCount || second < 0 || second >= d->sectionCount) + if (first < 0 || first >= d->sectionCount() || second < 0 || second >= d->sectionCount()) return; int firstSize = d->headerSectionSize(first); @@ -965,7 +965,7 @@ bool QHeaderView::isSectionHidden(int logicalIndex) const { Q_D(const QHeaderView); d->executePostedLayout(); - if (logicalIndex >= d->sectionHidden.count() || logicalIndex < 0 || logicalIndex >= d->sectionCount) + if (logicalIndex >= d->sectionHidden.count() || logicalIndex < 0 || logicalIndex >= d->sectionCount()) return false; int visual = visualIndex(logicalIndex); Q_ASSERT(visual != -1); @@ -1038,7 +1038,7 @@ int QHeaderView::count() const //Q_ASSERT(d->sectionCount == d->headerSectionCount()); // ### this may affect the lazy layout d->executePostedLayout(); - return d->sectionCount; + return d->sectionCount(); } /*! @@ -1057,11 +1057,11 @@ int QHeaderView::visualIndex(int logicalIndex) const return -1; d->executePostedLayout(); if (d->visualIndices.isEmpty()) { // nothing has been moved, so we have no mapping - if (logicalIndex < d->sectionCount) + if (logicalIndex < d->sectionCount()) return logicalIndex; } else if (logicalIndex < d->visualIndices.count()) { int visual = d->visualIndices.at(logicalIndex); - Q_ASSERT(visual < d->sectionCount); + Q_ASSERT(visual < d->sectionCount()); return visual; } return -1; @@ -1079,7 +1079,7 @@ int QHeaderView::visualIndex(int logicalIndex) const int QHeaderView::logicalIndex(int visualIndex) const { Q_D(const QHeaderView); - if (visualIndex < 0 || visualIndex >= d->sectionCount) + if (visualIndex < 0 || visualIndex >= d->sectionCount()) return -1; return d->logicalIndex(visualIndex); } @@ -1293,14 +1293,14 @@ void QHeaderView::setSortIndicator(int logicalIndex, Qt::SortOrder order) d->sortIndicatorSection = logicalIndex; d->sortIndicatorOrder = order; - if (logicalIndex >= d->sectionCount) { + if (logicalIndex >= d->sectionCount()) { emit sortIndicatorChanged(logicalIndex, order); return; // nothing to do } if (old != logicalIndex && ((logicalIndex >= 0 && resizeMode(logicalIndex) == ResizeToContents) - || old >= d->sectionCount || (old >= 0 && resizeMode(old) == ResizeToContents))) { + || old >= d->sectionCount() || (old >= 0 && resizeMode(old) == ResizeToContents))) { resizeSections(); d->viewport->update(); } else { @@ -1655,15 +1655,14 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent, Q_D(QHeaderView); if (parent != d->root) return; // we only handle changes in the top level - int oldCount = d->sectionCount; + int oldCount = d->sectionCount(); d->invalidateCachedSizeHint(); // add the new sections int insertAt = logicalFirst; - int insertCount = logicalLast - logicalFirst + 1; - d->sectionCount += insertCount; + QHeaderViewPrivate::SectionSpan span(d->defaultSectionSize, d->globalResizeMode); d->sectionStartposRecalc = true; @@ -1684,9 +1683,9 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent, // update resize mode section counts if (d->globalResizeMode == Stretch) - d->stretchSections = d->sectionCount; + d->stretchSections = d->sectionCount(); else if (d->globalResizeMode == ResizeToContents) - d->contentsSections = d->sectionCount; + d->contentsSections = d->sectionCount(); // clear selection cache d->sectionSelected.clear(); @@ -1723,7 +1722,7 @@ void QHeaderView::sectionsInserted(const QModelIndex &parent, for (int i = 0; i < logicalFirst; ++i) if (isSectionHidden(i)) newHiddenSectionSize[i] = d->hiddenSectionSize[i]; - for (int j = logicalLast + 1; j < d->sectionCount; ++j) + for (int j = logicalLast + 1; j < d->sectionCount(); ++j) if (isSectionHidden(j)) newHiddenSectionSize[j] = d->hiddenSectionSize[j - insertCount]; d->hiddenSectionSize = newHiddenSectionSize; @@ -1762,14 +1761,14 @@ void QHeaderViewPrivate::updateHiddenSections(int logicalFirst, int logicalLast) for (int i = 0; i < logicalFirst; ++i) if (q->isSectionHidden(i)) newHiddenSectionSize[i] = hiddenSectionSize[i]; - for (int j = logicalLast + 1; j < sectionCount; ++j) + for (int j = logicalLast + 1; j < sectionCount(); ++j) if (q->isSectionHidden(j)) newHiddenSectionSize[j - changeCount] = hiddenSectionSize[j]; hiddenSectionSize = newHiddenSectionSize; // remove sections from sectionsHidden if (!sectionHidden.isEmpty()) { - const int newsize = qMin(sectionCount - changeCount, sectionHidden.size()); + const int newsize = qMin(sectionCount() - changeCount, sectionHidden.size()); QBitArray newSectionHidden(newsize); for (int j = 0, k = 0; j < sectionHidden.size(); ++j) { const int logical = logicalIndex(j); @@ -1788,7 +1787,7 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent, if (parent != root) return; // we only handle changes in the top level if (qMin(logicalFirst, logicalLast) < 0 - || qMax(logicalLast, logicalFirst) >= sectionCount) + || qMax(logicalLast, logicalFirst) >= sectionCount()) return; int oldCount = q->count(); int changeCount = logicalLast - logicalFirst + 1; @@ -1802,8 +1801,8 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent, if (logicalFirst == logicalLast) { // Remove just one index. int l = logicalFirst; int visual = visualIndices.at(l); - Q_ASSERT(sectionCount == logicalIndices.count()); - for (int v = 0; v < sectionCount; ++v) { + Q_ASSERT(sectionCount() == logicalIndices.count()); + for (int v = 0; v < sectionCount(); ++v) { if (v > visual) { int logical = logicalIndices.at(v); --(visualIndices[logical]); @@ -1837,7 +1836,6 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent, } // ### handle sectionSelection (sectionHidden is handled by updateHiddenSections) } - sectionCount -= changeCount; // update sorting column if (sortIndicatorSection >= logicalFirst) { @@ -1848,7 +1846,7 @@ void QHeaderViewPrivate::_q_sectionsRemoved(const QModelIndex &parent, } // if we only have the last section (the "end" position) left, the header is empty - if (sectionCount <= 0) + if (sectionCount() <= 0) clear(); invalidateCachedSizeHint(); emit q->sectionCountChanged(oldCount, q->count()); @@ -1877,7 +1875,7 @@ void QHeaderViewPrivate::_q_layoutChanged() Q_Q(QHeaderView); viewport->update(); if (persistentHiddenSections.isEmpty() || modelIsEmpty()) { - if (modelSectionCount() != sectionCount) + if (modelSectionCount() != sectionCount()) q->initializeSections(); persistentHiddenSections.clear(); return; @@ -1894,7 +1892,7 @@ void QHeaderViewPrivate::_q_layoutChanged() : index.row()); q->setSectionHidden(logical, true); oldSectionHidden.setBit(logical, false); - } else if (!sectionCountChanged && (modelSectionCount() != sectionCount)) { + } else if (!sectionCountChanged && (modelSectionCount() != sectionCount())) { sectionCountChanged = true; break; } @@ -1918,7 +1916,7 @@ void QHeaderViewPrivate::_q_layoutChanged() void QHeaderView::initializeSections() { Q_D(QHeaderView); - const int oldCount = d->sectionCount; + const int oldCount = d->sectionCount(); const int newCount = d->modelSectionCount(); if (newCount <= 0) { d->clear(); @@ -1927,7 +1925,7 @@ void QHeaderView::initializeSections() const int min = qBound(0, oldCount, newCount - 1); initializeSections(min, newCount - 1); if (stretchLastSection()) // we've already gotten the size hint - d->lastSectionSize = sectionSize(logicalIndex(d->sectionCount - 1)); + d->lastSectionSize = sectionSize(logicalIndex(d->sectionCount() - 1)); //make sure we update the hidden sections if (newCount < oldCount) @@ -1947,13 +1945,14 @@ void QHeaderView::initializeSections(int start, int end) Q_ASSERT(end >= 0); d->invalidateCachedSizeHint(); + int oldCount = d->sectionCount(); - if (end + 1 < d->sectionCount) { + if (end + 1 < d->sectionCount()) { int newCount = end + 1; - d->removeSectionsFromSpans(newCount, d->sectionCount - 1); + d->removeSectionsFromSpans(newCount, d->sectionCount() - 1); if (!d->hiddenSectionSize.isEmpty()) { - if (d->sectionCount - newCount > d->hiddenSectionSize.count()) { - for (int i = end + 1; i < d->sectionCount; ++i) + if (oldCount - newCount > d->hiddenSectionSize.count()) { + for (int i = end + 1; i < d->sectionCount(); ++i) d->hiddenSectionSize.remove(i); } else { QHash::iterator it = d->hiddenSectionSize.begin(); @@ -1967,14 +1966,13 @@ void QHeaderView::initializeSections(int start, int end) } } - int oldCount = d->sectionCount; - d->sectionCount = end + 1; + int newSectionCount = end + 1; if (!d->logicalIndices.isEmpty()) { - if (oldCount <= d->sectionCount) { - d->logicalIndices.resize(d->sectionCount); - d->visualIndices.resize(d->sectionCount); - for (int i = oldCount; i < d->sectionCount; ++i) { + if (oldCount <= newSectionCount) { + d->logicalIndices.resize(newSectionCount); + d->visualIndices.resize(newSectionCount); + for (int i = oldCount; i < newSectionCount; ++i) { d->logicalIndices[i] = i; d->visualIndices[i] = i; } @@ -1982,30 +1980,30 @@ void QHeaderView::initializeSections(int start, int end) int j = 0; for (int i = 0; i < oldCount; ++i) { int v = d->logicalIndices.at(i); - if (v < d->sectionCount) { + if (v < newSectionCount) { d->logicalIndices[j] = v; d->visualIndices[v] = j; j++; } } - d->logicalIndices.resize(d->sectionCount); - d->visualIndices.resize(d->sectionCount); + d->logicalIndices.resize(newSectionCount); + d->visualIndices.resize(newSectionCount); } } if (d->globalResizeMode == Stretch) - d->stretchSections = d->sectionCount; + d->stretchSections = newSectionCount; else if (d->globalResizeMode == ResizeToContents) - d->contentsSections = d->sectionCount; + d->contentsSections = newSectionCount; if (!d->sectionHidden.isEmpty()) - d->sectionHidden.resize(d->sectionCount); + d->sectionHidden.resize(newSectionCount); - if (d->sectionCount > oldCount) + if (newSectionCount > oldCount) d->createSectionSpan(start, end, (end - start + 1) * d->defaultSectionSize, d->globalResizeMode); //Q_ASSERT(d->headerLength() == d->length); - if (d->sectionCount != oldCount) - emit sectionCountChanged(oldCount, d->sectionCount); + if (d->sectionCount() != oldCount) + emit sectionCountChanged(oldCount, d->sectionCount()); d->viewport->update(); } @@ -2996,7 +2994,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool delayedResize.stop(); executePostedLayout(); - if (sectionCount == 0) + if (sectionCount() == 0) return; if (resizeRecursionBlock) @@ -3016,7 +3014,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool int lengthToStrech = (orientation == Qt::Horizontal ? viewport->width() : viewport->height()); int numberOfStretchedSections = 0; QList section_sizes; - for (int i = 0; i < sectionCount; ++i) { + for (int i = 0; i < sectionCount(); ++i) { if (isVisualIndexHidden(i)) continue; @@ -3060,7 +3058,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive; // resize each section along the total length - for (int i = 0; i < sectionCount; ++i) { + for (int i = 0; i < sectionCount(); ++i) { int oldSectionLength = headerSectionSize(i); int newSectionLength = -1; QHeaderView::ResizeMode newSectionResizeMode = headerSectionResizeMode(i); @@ -3107,8 +3105,8 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool previousSectionResizeMode = newSectionResizeMode; } - createSectionSpan(spanStartSection, sectionCount - 1, - (sectionCount - spanStartSection) * previousSectionLength, + createSectionSpan(spanStartSection, sectionCount() - 1, + (sectionCount() - spanStartSection) * previousSectionLength, previousSectionResizeMode); //Q_ASSERT(headerLength() == length); resizeRecursionBlock = false; @@ -3144,7 +3142,6 @@ void QHeaderViewPrivate::clear() { if (state != NoClear) { length = 0; - sectionCount = 0; visualIndices.clear(); logicalIndices.clear(); sectionSelected.clear(); @@ -3205,7 +3202,7 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize) } // cascade the section size change - for (int i = visual + 1; i < sectionCount; ++i) { + for (int i = visual + 1; i < sectionCount(); ++i) { if (!sectionIsCascadable(i)) continue; int currentSectionSize = headerSectionSize(i); @@ -3261,7 +3258,7 @@ void QHeaderViewPrivate::cascadingResize(int visual, int newSize) // let the next section get the space from the resized section if (!sectionResized) { - for (int i = visual + 1; i < sectionCount; ++i) { + for (int i = visual + 1; i < sectionCount(); ++i) { if (!sectionIsCascadable(i)) continue; int currentSectionSize = headerSectionSize(i); @@ -3317,14 +3314,14 @@ void QHeaderViewPrivate::resizeSectionSpan(int visualIndex, int oldSize, int new int QHeaderViewPrivate::headerSectionSize(int visual) const { - if (visual < sectionCount && visual >= 0) + if (visual < sectionCount() && visual >= 0) return sectionSpans.at(visual).sectionSize(); return -1; } int QHeaderViewPrivate::headerSectionPosition(int visual) const { - if (visual < sectionCount && visual >= 0) { + if (visual < sectionCount() && visual >= 0) { if (sectionStartposRecalc) recalcSectionStartPos(); return sectionSpans.at(visual).calculated_startpos; @@ -3416,7 +3413,7 @@ void QHeaderViewPrivate::write(QDataStream &out) const out << hiddenSectionSize; out << length; - out << sectionCount; + out << sectionCount(); out << movableSections; out << clickableSections; out << highlightSelected; @@ -3452,7 +3449,8 @@ bool QHeaderViewPrivate::read(QDataStream &in) in >> hiddenSectionSize; in >> length; - in >> sectionCount; + int unusedSectionCount; // For compability + in >> unusedSectionCount; in >> movableSections; in >> clickableSections; in >> highlightSelected; diff --git a/src/widgets/itemviews/qheaderview_p.h b/src/widgets/itemviews/qheaderview_p.h index 2c657221dd..a2b0ef2180 100644 --- a/src/widgets/itemviews/qheaderview_p.h +++ b/src/widgets/itemviews/qheaderview_p.h @@ -84,7 +84,6 @@ public: pressed(-1), hover(-1), length(0), - sectionCount(0), movableSections(false), clickableSections(false), highlightSelected(false), @@ -137,11 +136,13 @@ public: inline void prepareSectionSelected() { if (!selectionModel || !selectionModel->hasSelection()) sectionSelected.clear(); - else if (sectionSelected.count() != sectionCount * 2) - sectionSelected.fill(false, sectionCount * 2); + else if (sectionSelected.count() != sectionCount() * 2) + sectionSelected.fill(false, sectionCount() * 2); else sectionSelected.fill(false); } + inline int sectionCount() const {return sectionSpans.count();} + inline bool reverse() const { return orientation == Qt::Horizontal && q_func()->isRightToLeft(); } @@ -182,11 +183,11 @@ public: } inline void initializeIndexMapping() const { - if (visualIndices.count() != sectionCount - || logicalIndices.count() != sectionCount) { - visualIndices.resize(sectionCount); - logicalIndices.resize(sectionCount); - for (int s = 0; s < sectionCount; ++s) { + if (visualIndices.count() != sectionCount() + || logicalIndices.count() != sectionCount()) { + visualIndices.resize(sectionCount()); + logicalIndices.resize(sectionCount()); + for (int s = 0; s < sectionCount(); ++s) { visualIndices[s] = s; logicalIndices[s] = s; } @@ -194,7 +195,7 @@ public: } inline void clearCascadingSections() { - firstCascadingSection = sectionCount; + firstCascadingSection = sectionSpans.count(); lastCascadingSection = 0; cascadingSectionSize.clear(); } @@ -265,7 +266,6 @@ public: int hover; int length; - int sectionCount; bool movableSections; bool clickableSections; bool highlightSelected; -- cgit v1.2.3 From b804b81288772b64dbd633c1e320f6e71a00b473 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Tue, 28 Feb 2012 14:57:29 +1000 Subject: Remove unused selftest data file. The private git history shows that the test program associated with this data file was missing from the original commit and was never subsequently added. Change-Id: I3401724ac04168158a48eb06436db83d3557711f Reviewed-by: Rohan McGovern --- tests/auto/testlib/selftests/expected_fatal.txt | 6 ------ tests/auto/testlib/selftests/selftests.qrc | 1 - 2 files changed, 7 deletions(-) delete mode 100644 tests/auto/testlib/selftests/expected_fatal.txt diff --git a/tests/auto/testlib/selftests/expected_fatal.txt b/tests/auto/testlib/selftests/expected_fatal.txt deleted file mode 100644 index a525fee0a1..0000000000 --- a/tests/auto/testlib/selftests/expected_fatal.txt +++ /dev/null @@ -1,6 +0,0 @@ -********* Start testing of tst_Fatal ********* -Config: Using QTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@ -PASS : tst_Fatal::initTestCase() -QFATAL : tst_Fatal::testFunction() A fatal error occured! Ouuiieee!! The world is coming to an end and I will die! Buhu! -Totals: 1 passed, 0 failed, 0 skipped -********* Finished testing of tst_Fatal ********* diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc index d05ac2a516..e39515e5be 100644 --- a/tests/auto/testlib/selftests/selftests.qrc +++ b/tests/auto/testlib/selftests/selftests.qrc @@ -71,7 +71,6 @@ expected_failinitdata.txt expected_failinitdata.xml expected_failinitdata.xunitxml - expected_fatal.txt expected_fetchbogus.lightxml expected_fetchbogus.txt expected_fetchbogus.xml -- cgit v1.2.3 From 99b997c4d5c4066866f4b4af04b925fcf17f144c Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 28 Feb 2012 16:07:07 +1000 Subject: Cleaned up examples/opengl/cube/cube.pro, removed message() It's arbitrary and confusing to put a message(OpenGL support is enabled) in this one OpenGL example and no others, especially since the message is output during configure. Change-Id: I7b55868d10c288f3459a7fda594fea1e6f45bf9a Reviewed-by: Toby Tomkins --- examples/opengl/cube/cube.pro | 9 --------- 1 file changed, 9 deletions(-) diff --git a/examples/opengl/cube/cube.pro b/examples/opengl/cube/cube.pro index ef6f526067..98a3082340 100644 --- a/examples/opengl/cube/cube.pro +++ b/examples/opengl/cube/cube.pro @@ -1,9 +1,3 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2010-06-23T12:55:35 -# -#------------------------------------------------- - QT += core gui widgets TARGET = cube @@ -12,7 +6,6 @@ TEMPLATE = app SOURCES += main.cpp contains(QT_CONFIG, opengl) { - message(Building with OpenGL support.) QT += opengl SOURCES += mainwidget.cpp \ @@ -29,8 +22,6 @@ contains(QT_CONFIG, opengl) { OTHER_FILES += \ vshader.glsl \ fshader.glsl -} else { - message(OpenGL support is not available.) } -- cgit v1.2.3 From 636e5c5d64479754b9d8d262bba64773e3b5cf93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 29 Feb 2012 08:34:57 +0100 Subject: Added helpful notice in configure about how to enable the xcb plugin. This should make it less confusing for people building Qt 5 on Linux. Change-Id: I3aa7151f790587d5944c837d701b1b1b580b4bc3 Reviewed-by: Alan Alpert --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 8b8fc7d008..4e6d42d8cb 100755 --- a/configure +++ b/configure @@ -5499,6 +5499,8 @@ if [ "$PLATFORM_QPA" = "yes" ]; then echo " If you really want to build without a QPA platform plugin you must pass" echo " -no-xcb and -no-wayland to configure. Doing this will produce a Qt that" echo " cannot run GUI applications." + echo " The dependencies needed for xcb to build are listed in" + echo " src/plugins/platforms/xcb/README" exit 1 fi fi -- cgit v1.2.3 From 8dfc86e0d6391a9e923557732a3ddc6c37d98b89 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Thu, 23 Feb 2012 21:07:42 +0000 Subject: Remove Mac/QPA collision breaking library linkage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prior to this change, explicitly passing -qpa to configure breaks compilation on Mac. This is due to a false dichotomy between MAC/QPA Change-Id: I52cacf96ae8d8d203787f9bbade417f2c55ab3f1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Morten Johan Sørvig --- configure | 2 -- 1 file changed, 2 deletions(-) diff --git a/configure b/configure index 4e6d42d8cb..c5ce9329c8 100755 --- a/configure +++ b/configure @@ -359,7 +359,6 @@ earlyArgParse() if [ "$PLATFORM_QPA" != "no" ]; then if [ "$PLATFORM_QPA" = "maybe" ]; then PLATFORM_X11=no - PLATFORM_MAC=no PLATFORM_QPA=yes fi else @@ -1222,7 +1221,6 @@ while [ "$#" -gt 0 ]; do ;; embedded-lite|qpa) PLATFORM_X11=no - PLATFORM_MAC=no PLATFORM_QPA=yes ;; sse) -- cgit v1.2.3 From ec234625c0bde3eeb67cd4681cb66277bdf115b3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 12:28:57 +0100 Subject: Remove include for no-longer-supported compiler. Change-Id: I162da3e373a0191f69e50e110114ef78c2d5fc66 Reviewed-by: Olivier Goffart --- src/corelib/tools/qstringbuilder.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 4c963185ad..0fd164c2e4 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -45,12 +45,6 @@ #include #include -#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) -# include -# endif -#endif - #include QT_BEGIN_HEADER -- cgit v1.2.3 From 8b33be0054517e7506f1ed4378232fa81e710df1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 22:27:48 +0100 Subject: QScopedValueRollback: make constructor explicit I'm not even sure whether you could implicitly convert a T& into a QScopedValueRollback, seeing as the constructor takes a non-const reference, but it looks wrong without explicit and QObject o = new QObject(parent); also won't compile even with implicit QObject(QObject*) under a conformant compiler because of the disabled copy constructor, and we still make QObject(QObject*) explicit, so add it here, too. Change-Id: I722a6e8431644e450fe2b401ccfb707a8e982380 Reviewed-by: Olivier Goffart Reviewed-by: Lars Knoll Reviewed-by: Shane Kearns --- src/corelib/tools/qscopedvaluerollback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index 23d2d9eda0..d53cabd315 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -51,7 +51,7 @@ template class QScopedValueRollback { public: - QScopedValueRollback(T &var) : + explicit QScopedValueRollback(T &var) : varRef(var) { oldValue = varRef; -- cgit v1.2.3 From 85e050b0b3f1eb36007abd6b12158ce3496a4dc4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 27 Feb 2012 22:06:54 +0100 Subject: Make qlocale.h not depend on qvariant.h. As a consequence, we have to add more explicit includes. Change-Id: Ib3137031f0554b846c7bbd08f1f7df10dfeb8e61 Reviewed-by: Olivier Goffart --- src/corelib/io/qstandardpaths_unix.cpp | 1 + src/corelib/json/qjsonarray.cpp | 1 + src/corelib/json/qjsondocument.cpp | 1 + src/corelib/json/qjsonobject.cpp | 1 + src/corelib/tools/qlocale.h | 1 - src/corelib/tools/qlocale_p.h | 2 +- 6 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index 62c846738e..5499751751 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -42,6 +42,7 @@ #include "qstandardpaths.h" #include #include +#include #include #include #include diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index 0eb1974147..6ffb9639f7 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "qjsonwriter_p.h" diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp index 8a7fa760ae..c2204bf696 100644 --- a/src/corelib/json/qjsondocument.cpp +++ b/src/corelib/json/qjsondocument.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "qjsonwriter_p.h" #include "qjsonparser_p.h" diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index b7af8c22cf..289a752c8b 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include "qjson_p.h" #include "qjsonwriter_p.h" diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index c029f627b2..2ecd934100 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -42,7 +42,6 @@ #ifndef QLOCALE_H #define QLOCALE_H -#include #include #include diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index c6902ca206..ad7c9706c4 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -55,7 +55,7 @@ #include "QtCore/qstring.h" #include "QtCore/qvarlengtharray.h" -#include "QtCore/qmetatype.h" +#include "QtCore/qvariant.h" #include "qlocale.h" -- cgit v1.2.3 From 612152fad8f531e66ecda9ef72eae32061af7139 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 27 Feb 2012 21:57:12 +0100 Subject: Make qobject_p.h not need qvariant.h. Move definition of ExtraData to the implementation file. As a side effect, we need to include qhash.h in some other places. Change-Id: I8bb4ec0940ae51c7d6961c9a51adb80fd444e1e3 Reviewed-by: Olivier Goffart --- src/corelib/io/qfilesystemwatcher_polling_p.h | 1 + src/corelib/kernel/qeventdispatcher_win_p.h | 1 + src/corelib/kernel/qobject.cpp | 10 ++++++++++ src/corelib/kernel/qobject_p.h | 11 +---------- src/gui/kernel/qopenglcontext_p.h | 2 -- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_polling_p.h b/src/corelib/io/qfilesystemwatcher_polling_p.h index 14f6345412..e50082c6d3 100644 --- a/src/corelib/io/qfilesystemwatcher_polling_p.h +++ b/src/corelib/io/qfilesystemwatcher_polling_p.h @@ -58,6 +58,7 @@ #include #include #include +#include #include "qfilesystemwatcher_p.h" diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index c404967e6a..a831ad39e8 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -55,6 +55,7 @@ #include "QtCore/qabstracteventdispatcher.h" #include "QtCore/qt_windows.h" +#include "QtCore/qhash.h" #include "qabstracteventdispatcher_p.h" diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8fa5dcdcff..2231518253 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -69,6 +69,16 @@ QT_BEGIN_NAMESPACE +struct QObjectPrivate::ExtraData +{ + ExtraData() {} +#ifndef QT_NO_USERDATA + QVector userData; +#endif + QList propertyNames; + QList propertyValues; +}; + static int DIRECT_CONNECTION_ONLY = 0; static int *queuedConnectionTypes(const QList &typeNames) diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index fa1aee8173..f75d4464b2 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,7 +60,6 @@ #include "QtCore/qlist.h" #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" -#include "QtCore/qvariant.h" QT_BEGIN_NAMESPACE @@ -98,16 +97,8 @@ class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) + struct ExtraData; public: - struct ExtraData - { - ExtraData() {} -#ifndef QT_NO_USERDATA - QVector userData; -#endif - QList propertyNames; - QList propertyValues; - }; typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **); struct Connection diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 3e2c35f088..d5c4d6c762 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -49,9 +49,7 @@ #include #include -#ifndef QT_NO_DEBUG #include -#endif QT_BEGIN_HEADER -- cgit v1.2.3 From e1cc0d6bbc2c65b10f23b2935a68a3a34b7c26a0 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 11:54:29 +0100 Subject: Allow QChar::SpecialCharacter with QStringBuilder. Change-Id: I3c91fd516bb13e5534aa6f26ee9df745c990dfb5 Reviewed-by: Olivier Goffart --- src/corelib/tools/qstringbuilder.h | 10 ++++++++++ .../tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp | 3 +++ 2 files changed, 13 insertions(+) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 0fd164c2e4..e34425be7e 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -167,6 +167,16 @@ template <> struct QConcatenable : private QAbstractConcatenable { *out++ = c; } }; +template <> struct QConcatenable : private QAbstractConcatenable +{ + typedef QChar::SpecialCharacter type; + typedef QString ConvertTo; + enum { ExactSize = true }; + static int size(const QChar::SpecialCharacter) { return 1; } + static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out) + { *out++ = c; } +}; + template <> struct QConcatenable : private QAbstractConcatenable { typedef QCharRef type; diff --git a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp index afc16078b8..556b9ac16a 100644 --- a/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp +++ b/tests/auto/corelib/tools/qstringbuilder/qstringbuilder1/stringbuilder.cpp @@ -73,6 +73,7 @@ void runScenario() QString string(l1string); QStringRef stringref(&string, 2, 10); QLatin1Char achar('c'); + QChar::SpecialCharacter special(QChar::Nbsp); QString r2(QLatin1String(LITERAL LITERAL)); QString r3 = QString::fromUtf8(UTF8_LITERAL UTF8_LITERAL); QString r; @@ -97,6 +98,8 @@ void runScenario() QCOMPARE(r, QString(string P achar)); r = achar + string; QCOMPARE(r, QString(achar P string)); + r = special + string; + QCOMPARE(r, QString(special P string)); #ifdef Q_COMPILER_UNICODE_STRINGS r = QStringLiteral(UNICODE_LITERAL); -- cgit v1.2.3 From 85161946337c25b1d23d661d4d748ab0270db2f4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 14:49:19 +0100 Subject: don't duplicate QLibraryInfo declaration there is no reason for doing that. there is even reason for *not* doing it (the enums running out of sync). Change-Id: Ieb7d015ca497a6675cc85da4c2e0af0c1533dd7a Reviewed-by: Joerg Bornemann --- qmake/option.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/qmake/option.h b/qmake/option.h index b8a3b561fa..b812f14a49 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -46,6 +46,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -216,28 +217,6 @@ private: inline QString fixEnvVariables(const QString &x) { return Option::fixString(x, Option::FixEnvVars); } inline QStringList splitPathList(const QString &paths) { return paths.split(Option::dirlist_sep); } -// this is a stripped down version of the one found in QtCore -class QLibraryInfo -{ -public: - enum LibraryLocation - { - PrefixPath, - DocumentationPath, - HeadersPath, - LibrariesPath, - BinariesPath, - PluginsPath, - DataPath, - TranslationsPath, - SettingsPath, - ExamplesPath, - ImportsPath, - TestsPath - }; - static QString location(LibraryLocation); -}; - QT_END_NAMESPACE #endif // OPTION_H -- cgit v1.2.3 From da08210494c132e8990ae3ba2ddb78983d266461 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 09:54:53 +0100 Subject: remove pointless ifdefs configure always defines all of these constants. the exception is SettingsPath which is unix-only, so make the #ifdef explicit about that. Change-Id: I339d2d7cb9d188a8e74d79310c3a80b5d4dbb806 Reviewed-by: Thiago Macieira --- src/corelib/global/qlibraryinfo.cpp | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index c871675334..72db761e2d 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -226,66 +226,44 @@ QLibraryInfo::location(LibraryLocation loc) if(!QLibraryInfoPrivate::configuration()) { const char *path = 0; switch (loc) { -#ifdef QT_CONFIGURE_PREFIX_PATH case PrefixPath: path = QT_CONFIGURE_PREFIX_PATH; break; -#endif -#ifdef QT_CONFIGURE_DOCUMENTATION_PATH case DocumentationPath: path = QT_CONFIGURE_DOCUMENTATION_PATH; break; -#endif -#ifdef QT_CONFIGURE_HEADERS_PATH case HeadersPath: path = QT_CONFIGURE_HEADERS_PATH; break; -#endif -#ifdef QT_CONFIGURE_LIBRARIES_PATH case LibrariesPath: path = QT_CONFIGURE_LIBRARIES_PATH; break; -#endif -#ifdef QT_CONFIGURE_BINARIES_PATH case BinariesPath: path = QT_CONFIGURE_BINARIES_PATH; break; -#endif -#ifdef QT_CONFIGURE_PLUGINS_PATH case PluginsPath: path = QT_CONFIGURE_PLUGINS_PATH; break; -#endif -#ifdef QT_CONFIGURE_IMPORTS_PATH case ImportsPath: path = QT_CONFIGURE_IMPORTS_PATH; break; -#endif -#ifdef QT_CONFIGURE_DATA_PATH case DataPath: path = QT_CONFIGURE_DATA_PATH; break; -#endif -#ifdef QT_CONFIGURE_TRANSLATIONS_PATH case TranslationsPath: path = QT_CONFIGURE_TRANSLATIONS_PATH; break; -#endif -#ifdef QT_CONFIGURE_SETTINGS_PATH +#ifndef Q_OS_WIN // On Windows we use the registry case SettingsPath: path = QT_CONFIGURE_SETTINGS_PATH; break; #endif -#ifdef QT_CONFIGURE_EXAMPLES_PATH case ExamplesPath: path = QT_CONFIGURE_EXAMPLES_PATH; break; -#endif -#ifdef QT_CONFIGURE_TESTS_PATH case TestsPath: path = QT_CONFIGURE_TESTS_PATH; break; -#endif default: break; } -- cgit v1.2.3 From 3b1b5be911102402cb0d932a4da87319d2d04435 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 10:20:34 +0100 Subject: remove bizarre padstring voodoo evidently, The Author had no clue that the compiler will do that automatically. as it happens, the windows configure already did it right. Change-Id: I7ebc018c254b316205348874ffa527526329b630 Reviewed-by: Thiago Macieira --- config.tests/unix/padstring | 22 ------------ configure | 87 +++++++++++++++------------------------------ 2 files changed, 29 insertions(+), 80 deletions(-) delete mode 100755 config.tests/unix/padstring diff --git a/config.tests/unix/padstring b/config.tests/unix/padstring deleted file mode 100755 index 283475d071..0000000000 --- a/config.tests/unix/padstring +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -LEN="$1" -STR="$2" -PAD='\0' -STRLEN=`echo $STR | wc -c` -RES="$STR" - -EXTRALEN=`expr $LEN - $STRLEN` -while [ "$EXTRALEN" -gt 32 ]; do - RES="$RES$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD$PAD" - EXTRALEN=`expr $EXTRALEN - 32` -done -while [ "$EXTRALEN" -gt 0 ]; do - RES="$RES$PAD" - EXTRALEN=`expr $EXTRALEN - 1` -done -cat < "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" </dev/null 2>&1; then - EVALKEY=`"$relpath/config.tests/unix/padstring" 524 "qt_qevalkey="` + EVALKEY=qt_qevalkey= fi if [ -n "$EVALKEY" ]; then -- cgit v1.2.3 From 486bde8372b30a2133e911268147704c699f8284 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 11:01:52 +0100 Subject: make qlibraryinfo table-driven switch blocks are noisy. this is nicer. reshuffled the LibraryLocation enum to make table lookups possible and future-safe. using pointer-free tables to avoid adding data relocations. Change-Id: I70ec2c2142ce02a15e67284e4b285d754d930da3 Reviewed-by: Thiago Macieira --- configure | 65 +++++++++---------- src/corelib/global/qlibraryinfo.cpp | 120 +++++++++--------------------------- src/corelib/global/qlibraryinfo.h | 8 +-- tools/configure/configureapp.cpp | 59 ++++++++---------- 4 files changed, 90 insertions(+), 162 deletions(-) diff --git a/configure b/configure index 3101982f84..7aa8adaa43 100755 --- a/configure +++ b/configure @@ -3995,36 +3995,40 @@ if [ ! -z "$QT_HOST_PREFIX" ]; then #if defined(QT_BOOTSTRAPPED) || defined(QT_BUILD_QMAKE) /* Installation Info */ -static const char qt_configure_prefix_path_str [256 + 12] = "qt_prfxpath=$QT_HOST_PREFIX"; -static const char qt_configure_documentation_path_str[256 + 12] = "qt_docspath=$QT_HOST_PREFIX/doc"; -static const char qt_configure_headers_path_str [256 + 12] = "qt_hdrspath=$QT_HOST_PREFIX/include"; -static const char qt_configure_libraries_path_str [256 + 12] = "qt_libspath=$QT_HOST_PREFIX/lib"; -static const char qt_configure_binaries_path_str [256 + 12] = "qt_binspath=$QT_HOST_PREFIX/bin"; -static const char qt_configure_plugins_path_str [256 + 12] = "qt_plugpath=$QT_HOST_PREFIX/plugins"; -static const char qt_configure_imports_path_str [256 + 12] = "qt_impspath=$QT_HOST_PREFIX/IMPORTS"; -static const char qt_configure_data_path_str [256 + 12] = "qt_datapath=$QT_HOST_PREFIX"; -static const char qt_configure_translations_path_str [256 + 12] = "qt_trnspath=$QT_HOST_PREFIX/translations"; -static const char qt_configure_settings_path_str [256 + 12] = "qt_stngpath=$QT_INSTALL_SETTINGS"; -static const char qt_configure_examples_path_str [256 + 12] = "qt_xmplpath=$QT_INSTALL_EXAMPLES"; -static const char qt_configure_tests_path_str [256 + 12] = "qt_tstspath=$QT_INSTALL_TESTS"; +static const char qt_configure_prefix_path_strs[][256 + 12] = { + "qt_prfxpath=$QT_HOST_PREFIX", + "qt_docspath=$QT_HOST_PREFIX/doc", + "qt_hdrspath=$QT_HOST_PREFIX/include", + "qt_libspath=$QT_HOST_PREFIX/lib", + "qt_binspath=$QT_HOST_PREFIX/bin", + "qt_plugpath=$QT_HOST_PREFIX/plugins", + "qt_impspath=$QT_HOST_PREFIX/IMPORTS", + "qt_datapath=$QT_HOST_PREFIX", + "qt_trnspath=$QT_HOST_PREFIX/translations", + "qt_xmplpath=$QT_INSTALL_EXAMPLES", + "qt_tstspath=$QT_INSTALL_TESTS", +}; +static const char qt_configure_settings_path_str[256 + 12] = "qt_stngpath=$QT_INSTALL_SETTINGS"; #else // QT_BOOTSTRAPPED EOF fi cat >> "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" <= 0 && loc < sizeof(qt_configure_prefix_path_strs)/sizeof(qt_configure_prefix_path_strs[0])) + path = qt_configure_prefix_path_strs[loc] + 12; #ifndef Q_OS_WIN // On Windows we use the registry - case SettingsPath: + else if (loc == SettingsPath) path = QT_CONFIGURE_SETTINGS_PATH; - break; #endif - case ExamplesPath: - path = QT_CONFIGURE_EXAMPLES_PATH; - break; - case TestsPath: - path = QT_CONFIGURE_TESTS_PATH; - break; - default: - break; - } if (path) ret = QString::fromLocal8Bit(path); } else { QString key; QString defaultValue; - switch(loc) { - case PrefixPath: - key = QLatin1String("Prefix"); - break; - case DocumentationPath: - key = QLatin1String("Documentation"); - defaultValue = QLatin1String("doc"); - break; - case HeadersPath: - key = QLatin1String("Headers"); - defaultValue = QLatin1String("include"); - break; - case LibrariesPath: - key = QLatin1String("Libraries"); - defaultValue = QLatin1String("lib"); - break; - case BinariesPath: - key = QLatin1String("Binaries"); - defaultValue = QLatin1String("bin"); - break; - case PluginsPath: - key = QLatin1String("Plugins"); - defaultValue = QLatin1String("plugins"); - break; - case ImportsPath: - key = QLatin1String("Imports"); - defaultValue = QLatin1String("imports"); - break; - case DataPath: - key = QLatin1String("Data"); - break; - case TranslationsPath: - key = QLatin1String("Translations"); - defaultValue = QLatin1String("translations"); - break; - case SettingsPath: - key = QLatin1String("Settings"); - break; - case ExamplesPath: - key = QLatin1String("Examples"); - break; - case TestsPath: - key = QLatin1String("Tests"); - defaultValue = QLatin1String("tests"); - break; - default: - break; + if (loc >= 0 && loc < sizeof(qtConfEntries)/sizeof(qtConfEntries[0])) { + key = QLatin1String(qtConfEntries[loc].key); + defaultValue = QLatin1String(qtConfEntries[loc].value); } +#ifndef Q_OS_WIN // On Windows we use the registry + else if (loc == SettingsPath) + key = QLatin1String("Settings"); +#endif if(!key.isNull()) { QSettings *config = QLibraryInfoPrivate::configuration(); @@ -391,9 +331,9 @@ QLibraryInfo::location(LibraryLocation loc) \value ImportsPath The location of installed QML extensions to import. \value DataPath The location of general Qt data. \value TranslationsPath The location of translation information for Qt strings. - \value SettingsPath The location for Qt settings. \value ExamplesPath The location for examples upon install. \value TestsPath The location of installed Qt testcases. + \value SettingsPath The location for Qt settings. Not applicable on Windows. \sa location() */ @@ -421,9 +361,9 @@ void qt_core_boilerplate() "Library path: %s\n" "Include path: %s\n", qt_configure_installation + 12, - qt_configure_prefix_path_str + 12, - qt_configure_libraries_path_str + 12, - qt_configure_headers_path_str + 12); + qt_configure_prefix_path_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::PrefixPath] + 12, + qt_configure_prefix_path_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::LibrariesPath] + 12, + qt_configure_prefix_path_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::HeadersPath] + 12); QT_PREPEND_NAMESPACE(qDumpCPUFeatures)(); diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 66f3d40792..f6234d1eb4 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -66,18 +66,18 @@ public: enum LibraryLocation { - PrefixPath, + PrefixPath = 0, DocumentationPath, HeadersPath, LibrariesPath, BinariesPath, PluginsPath, + ImportsPath, DataPath, TranslationsPath, - SettingsPath, ExamplesPath, - ImportsPath, - TestsPath + TestsPath, + SettingsPath = 100 }; static QString location(LibraryLocation); // ### Qt 5: consider renaming it to path() diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index b7eeea6b60..e4c9bb2010 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2857,48 +2857,41 @@ void Configure::generateConfigfiles() << endl; if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) tmpStream << "#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)" << endl; - tmpStream << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << escapeSeparators(dictionary["QT_INSTALL_PREFIX"]) << "\";" << endl - << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << escapeSeparators(dictionary["QT_INSTALL_DOCS"]) << "\";" << endl - << "static const char qt_configure_headers_path_str [512 + 12] = \"qt_hdrspath=" << escapeSeparators(dictionary["QT_INSTALL_HEADERS"]) << "\";" << endl - << "static const char qt_configure_libraries_path_str [512 + 12] = \"qt_libspath=" << escapeSeparators(dictionary["QT_INSTALL_LIBS"]) << "\";" << endl - << "static const char qt_configure_binaries_path_str [512 + 12] = \"qt_binspath=" << escapeSeparators(dictionary["QT_INSTALL_BINS"]) << "\";" << endl - << "static const char qt_configure_plugins_path_str [512 + 12] = \"qt_plugpath=" << escapeSeparators(dictionary["QT_INSTALL_PLUGINS"]) << "\";" << endl - << "static const char qt_configure_imports_path_str [512 + 12] = \"qt_impspath=" << escapeSeparators(dictionary["QT_INSTALL_IMPORTS"]) << "\";" << endl - << "static const char qt_configure_data_path_str [512 + 12] = \"qt_datapath=" << escapeSeparators(dictionary["QT_INSTALL_DATA"]) << "\";" << endl - << "static const char qt_configure_translations_path_str [512 + 12] = \"qt_trnspath=" << escapeSeparators(dictionary["QT_INSTALL_TRANSLATIONS"]) << "\";" << endl - << "static const char qt_configure_examples_path_str [512 + 12] = \"qt_xmplpath=" << escapeSeparators(dictionary["QT_INSTALL_EXAMPLES"]) << "\";" << endl - << "static const char qt_configure_tests_path_str [512 + 12] = \"qt_tstspath=" << escapeSeparators(dictionary["QT_INSTALL_TESTS"]) << "\";" << endl + tmpStream << "static const char qt_configure_prefix_path_strs[][12 + 512] = {" << endl + << " \"qt_prfxpath=" << escapeSeparators(dictionary["QT_INSTALL_PREFIX"]) << "\"," << endl + << " \"qt_docspath=" << escapeSeparators(dictionary["QT_INSTALL_DOCS"]) << "\"," << endl + << " \"qt_hdrspath=" << escapeSeparators(dictionary["QT_INSTALL_HEADERS"]) << "\"," << endl + << " \"qt_libspath=" << escapeSeparators(dictionary["QT_INSTALL_LIBS"]) << "\"," << endl + << " \"qt_binspath=" << escapeSeparators(dictionary["QT_INSTALL_BINS"]) << "\"," << endl + << " \"qt_plugpath=" << escapeSeparators(dictionary["QT_INSTALL_PLUGINS"]) << "\"," << endl + << " \"qt_impspath=" << escapeSeparators(dictionary["QT_INSTALL_IMPORTS"]) << "\"," << endl + << " \"qt_datapath=" << escapeSeparators(dictionary["QT_INSTALL_DATA"]) << "\"," << endl + << " \"qt_trnspath=" << escapeSeparators(dictionary["QT_INSTALL_TRANSLATIONS"]) << "\"," << endl + << " \"qt_xmplpath=" << escapeSeparators(dictionary["QT_INSTALL_EXAMPLES"]) << "\"," << endl + << " \"qt_tstspath=" << escapeSeparators(dictionary["QT_INSTALL_TESTS"]) << "\"," << endl + << "};" << endl //<< "static const char qt_configure_settings_path_str [256] = \"qt_stngpath=" << escapeSeparators(dictionary["QT_INSTALL_SETTINGS"]) << "\";" << endl ; if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) { tmpStream << "#else" << endl - << "static const char qt_configure_prefix_path_str [512 + 12] = \"qt_prfxpath=" << escapeSeparators(dictionary[ "QT_HOST_PREFIX" ]) << "\";" << endl - << "static const char qt_configure_documentation_path_str[512 + 12] = \"qt_docspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/doc", true) <<"\";" << endl - << "static const char qt_configure_headers_path_str [512 + 12] = \"qt_hdrspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/include", true) <<"\";" << endl - << "static const char qt_configure_libraries_path_str [512 + 12] = \"qt_libspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/lib", true) <<"\";" << endl - << "static const char qt_configure_binaries_path_str [512 + 12] = \"qt_binspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/bin", true) <<"\";" << endl - << "static const char qt_configure_plugins_path_str [512 + 12] = \"qt_plugpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/plugins", true) <<"\";" << endl - << "static const char qt_configure_imports_path_str [512 + 12] = \"qt_impspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/imports", true) <<"\";" << endl - << "static const char qt_configure_data_path_str [512 + 12] = \"qt_datapath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ], true) <<"\";" << endl - << "static const char qt_configure_translations_path_str [512 + 12] = \"qt_trnspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/translations", true) <<"\";" << endl - << "static const char qt_configure_examples_path_str [512 + 12] = \"qt_xmplpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/example", true) <<"\";" << endl - << "static const char qt_configure_tests_path_str [512 + 12] = \"qt_tstspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/tests", true) <<"\";" << endl + << "static const char qt_configure_prefix_path_strs[][12 + 512] = {" << endl + << " \"qt_prfxpath=" << escapeSeparators(dictionary[ "QT_HOST_PREFIX" ]) << "\";" << endl + << " \"qt_docspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/doc", true) <<"\"," << endl + << " \"qt_hdrspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/include", true) <<"\"," << endl + << " \"qt_libspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/lib", true) <<"\"," << endl + << " \"qt_binspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/bin", true) <<"\"," << endl + << " \"qt_plugpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/plugins", true) <<"\"," << endl + << " \"qt_impspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/imports", true) <<"\"," << endl + << " \"qt_datapath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ], true) <<"\"," << endl + << " \"qt_trnspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/translations", true) <<"\"," << endl + << " \"qt_xmplpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/example", true) <<"\"," << endl + << " \"qt_tstspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/tests", true) <<"\"," << endl + << "};" << endl << "#endif //QT_BOOTSTRAPPED" << endl; } tmpStream << "/* strlen( \"qt_lcnsxxxx\") == 12 */" << endl << "#define QT_CONFIGURE_LICENSEE qt_configure_licensee_str + 12;" << endl << "#define QT_CONFIGURE_LICENSED_PRODUCTS qt_configure_licensed_products_str + 12;" << endl - << "#define QT_CONFIGURE_PREFIX_PATH qt_configure_prefix_path_str + 12;" << endl - << "#define QT_CONFIGURE_DOCUMENTATION_PATH qt_configure_documentation_path_str + 12;" << endl - << "#define QT_CONFIGURE_HEADERS_PATH qt_configure_headers_path_str + 12;" << endl - << "#define QT_CONFIGURE_LIBRARIES_PATH qt_configure_libraries_path_str + 12;" << endl - << "#define QT_CONFIGURE_BINARIES_PATH qt_configure_binaries_path_str + 12;" << endl - << "#define QT_CONFIGURE_PLUGINS_PATH qt_configure_plugins_path_str + 12;" << endl - << "#define QT_CONFIGURE_IMPORTS_PATH qt_configure_imports_path_str + 12;" << endl - << "#define QT_CONFIGURE_DATA_PATH qt_configure_data_path_str + 12;" << endl - << "#define QT_CONFIGURE_TRANSLATIONS_PATH qt_configure_translations_path_str + 12;" << endl - << "#define QT_CONFIGURE_EXAMPLES_PATH qt_configure_examples_path_str + 12;" << endl - << "#define QT_CONFIGURE_TESTS_PATH qt_configure_tests_path_str + 12;" << endl //<< "#define QT_CONFIGURE_SETTINGS_PATH qt_configure_settings_path_str + 12;" << endl << endl; -- cgit v1.2.3 From 1ff1486d5372177798ea3c8785a4b80a1f6cbe1e Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 22:39:07 +0100 Subject: QCryptographicHash: make constructor explicit The copy constructor of QCH is disabled, so there's no point in providing an implicit conversion from the Algorithm enum anyway, so make the ctor explicit. Change-Id: I4ea74ffb0963b4f49415da17778c3e6050454a6b Reviewed-by: Olivier Goffart --- src/corelib/tools/qcryptographichash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h index 2bfc03373a..6ebe389faf 100644 --- a/src/corelib/tools/qcryptographichash.h +++ b/src/corelib/tools/qcryptographichash.h @@ -65,7 +65,7 @@ public: Sha512 }; - QCryptographicHash(Algorithm method); + explicit QCryptographicHash(Algorithm method); ~QCryptographicHash(); void reset(); -- cgit v1.2.3 From e28be90dea1414e875d9f45f6a1d3e3f7c9ab7ec Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 12:49:00 +0100 Subject: Fix build of QWizard tests with QT_USE_QSTRINGBUILDER Change-Id: Id276cdb9b84c61bf75a5bde149142f39f52f563e Reviewed-by: Olivier Goffart --- tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp index 872c13216f..9d9b55cafd 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp @@ -562,8 +562,8 @@ void tst_QWizard::setDefaultProperty() // make sure the data structure is reasonable for (int i = 0; i < 200000; ++i) { - wizard.setDefaultProperty("QLineEdit", "x" + QByteArray::number(i), 0); - wizard.setDefaultProperty("QLabel", "y" + QByteArray::number(i), 0); + wizard.setDefaultProperty("QLineEdit", QByteArray("x" + QByteArray::number(i)).constData(), 0); + wizard.setDefaultProperty("QLabel", QByteArray("y" + QByteArray::number(i)).constData(), 0); } } -- cgit v1.2.3 From 98ecbf1f50c829f55effc012aeb835f99cb7fcdf Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 12:50:23 +0100 Subject: Fix build of QImageReader tests with QT_USE_QSTRINGBUILDER. Change-Id: I789d99d0741bc178d2d7fd82558edc684eb6daf8 Reviewed-by: Olivier Goffart --- tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index 96171740e2..dd839ec0ae 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -1368,7 +1368,7 @@ void tst_QImageReader::readFromResources() SKIP_IF_UNSUPPORTED(format); for (int i = 0; i < 2; ++i) { - QString file = i ? (":/images/" + fileName) : (prefix + fileName); + QString file = i ? QString(QStringLiteral(":/images/") + fileName) : QString(prefix + fileName); { // suppress warnings if we expect them if (!message.isEmpty()) { -- cgit v1.2.3 From 9b5cdccc02e3a3f173359f4a71d6143c290a1342 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 29 Feb 2012 08:31:41 +0100 Subject: Skip test tst_QTextScriptEngine::thaiWithZWJ on Windows. Change-Id: I9286ae8b1200b2d6638d1257a872450a9886fce0 Reviewed-by: Friedemann Kleint Reviewed-by: Sergio Ahumada --- tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp index 7c9a83eaa4..a88e93c93e 100644 --- a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp @@ -1283,6 +1283,9 @@ void tst_QTextScriptEngine::thaiIsolatedSaraAm() void tst_QTextScriptEngine::thaiWithZWJ() { +#ifdef Q_OS_WIN + QSKIP("This test currently fails on Windows - QTBUG-24565"); +#endif QString s(QString::fromUtf8("ร‍ร‌.ร.“ร…ร”ร\xA0ร本ร") + QChar(0x0363)/*superscript 'a', for testing Inherited class*/); QTextLayout layout(s); layout.beginLayout(); -- cgit v1.2.3 From 39e616c15980153d76fda516ba42824599a45e42 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Wed, 29 Feb 2012 14:20:11 +0100 Subject: QPlatformTheme: Add virtual destructor. Change-Id: I78aab57cc16ef4542bfb88c81dd6a9d8b4c4d853 Reviewed-by: Bradley T. Hughes --- src/gui/kernel/qplatformtheme_qpa.cpp | 5 +++++ src/gui/kernel/qplatformtheme_qpa.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/gui/kernel/qplatformtheme_qpa.cpp b/src/gui/kernel/qplatformtheme_qpa.cpp index 3f6b69b902..3fdece70ea 100644 --- a/src/gui/kernel/qplatformtheme_qpa.cpp +++ b/src/gui/kernel/qplatformtheme_qpa.cpp @@ -102,6 +102,11 @@ QT_BEGIN_NAMESPACE \sa themeHint(), QStyle::pixelMetric() */ +QPlatformTheme::~QPlatformTheme() +{ + +} + QPlatformMenu *QPlatformTheme::createPlatformMenu(QMenu *menu) const { Q_UNUSED(menu); diff --git a/src/gui/kernel/qplatformtheme_qpa.h b/src/gui/kernel/qplatformtheme_qpa.h index 31a52a9391..3610a3c1c8 100644 --- a/src/gui/kernel/qplatformtheme_qpa.h +++ b/src/gui/kernel/qplatformtheme_qpa.h @@ -99,6 +99,8 @@ public: CdeKeyboardScheme }; + virtual ~QPlatformTheme(); + virtual QPlatformMenu *createPlatformMenu(QMenu *menu = 0) const; virtual QPlatformMenuBar *createPlatformMenuBar(QMenuBar *menuBar = 0) const; -- cgit v1.2.3 From bcb0f28a4d8625e546ae6d43e1365cc1f8b5373c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 Feb 2012 14:18:08 +0100 Subject: Fix tests of QMimeDatabase. - Use temporary directories to avoid instabilities due to remains of previous failed tests and locked directories. - Replace SRCDIR by QFINDTESTDATA(), reference only the freedesktop.org.xml contained in the Qt source tree by $$QT.corelib.sources. - Improve some error messages, test suite instructions for Windows. Change-Id: Idee8e3767ef0a8299df3bdaaac20334164878db0 Reviewed-by: Friedemann Kleint Reviewed-by: David Faure --- .../qmimedatabase-cache/qmimedatabase-cache.pro | 2 +- .../tst_qmimedatabase-cache.cpp | 9 +- .../qmimedatabase-xml/qmimedatabase-xml.pro | 2 +- .../qmimedatabase-xml/tst_qmimedatabase-xml.cpp | 4 +- .../mimetypes/qmimedatabase/qmimedatabase.pro | 2 +- .../mimetypes/qmimedatabase/tst_qmimedatabase.cpp | 157 ++++++++++++++------- .../mimetypes/qmimedatabase/tst_qmimedatabase.h | 10 +- 7 files changed, 121 insertions(+), 65 deletions(-) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro index 815401ce1e..ba68167a6f 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/qmimedatabase-cache.pro @@ -7,6 +7,6 @@ QT = core testlib concurrent SOURCES = tst_qmimedatabase-cache.cpp HEADERS = ../tst_qmimedatabase.h -DEFINES += SRCDIR='"\\"$$PWD/../\\""' +DEFINES += CORE_SOURCES='"\\"$$QT.core.sources\\""' *-g++*:QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror -Wshadow -Wno-long-long -Wnon-virtual-dtor diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp index 205331d4dd..5ef04dc01d 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-cache/tst_qmimedatabase-cache.cpp @@ -47,10 +47,9 @@ #include "../tst_qmimedatabase.cpp" -tst_QMimeDatabase::tst_QMimeDatabase() +void tst_QMimeDatabase::init() { - QDir here = QDir::currentPath(); - const QString tempMime = here.absolutePath() + QString::fromLatin1("/mime"); - runUpdateMimeDatabase(tempMime); - QVERIFY(QFile::exists(tempMime + QString::fromLatin1("/mime.cache"))); + const QString mimeDirName = m_globalXdgDir + QStringLiteral("/mime"); + runUpdateMimeDatabase(mimeDirName); + QVERIFY(QFile::exists(mimeDirName + QStringLiteral("/mime.cache"))); } diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro index ac7515f781..4c00e84fc1 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/qmimedatabase-xml.pro @@ -9,6 +9,6 @@ CONFIG += depend_includepath SOURCES += tst_qmimedatabase-xml.cpp HEADERS += ../tst_qmimedatabase.h -DEFINES += SRCDIR='"\\"$$PWD/../\\""' +DEFINES += CORE_SOURCES='"\\"$$QT.core.sources\\""' *-g++*:QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror -Wshadow -Wno-long-long -Wnon-virtual-dtor diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp index 13ca372290..30c7677198 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase-xml/tst_qmimedatabase-xml.cpp @@ -40,10 +40,8 @@ ****************************************************************************/ #include "../tst_qmimedatabase.h" -#include -#include -tst_QMimeDatabase::tst_QMimeDatabase() +void tst_QMimeDatabase::init() { qputenv("QT_NO_MIME_CACHE", "1"); } diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro index 876b4377dd..1ff5546e5c 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro +++ b/tests/auto/corelib/mimetypes/qmimedatabase/qmimedatabase.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs SUBDIRS = qmimedatabase-xml -unix: SUBDIRS += qmimedatabase-cache +unix:!mac: SUBDIRS += qmimedatabase-cache diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 858f977a72..200944d198 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -44,49 +44,85 @@ #include "qstandardpaths.h" #include +#include +#include #include #include #include +static const char yastFileName[] ="yast2-metapackage-handler-mimetypes.xml"; + void initializeLang() { qputenv("LC_ALL", ""); qputenv("LANG", "en_US"); + QCoreApplication::setApplicationName("tst_qmimedatabase"); // temporary directory pattern +} + +static inline QString testSuiteWarning() +{ + + QString result; + QTextStream str(&result); + str << "\nCannot find the shared-mime-info test suite\nstarting from: " + << QDir::toNativeSeparators(QDir::currentPath()) << "\n" + "cd " << QDir::toNativeSeparators(QStringLiteral("tests/auto/corelib/mimetypes/qmimedatabase")) << "\n" + "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-0.zip\n" + "unzip Release-1-0.zip\n"; +#ifdef Q_OS_WIN + str << "mkdir testfiles\nxcopy /s Release-1-0\\tests testfiles\n"; +#else + str << "ln -s Release-1-0/tests testfiles\n"; +#endif + return result; } // Set LANG before QCoreApplication is created Q_CONSTRUCTOR_FUNCTION(initializeLang) +tst_QMimeDatabase::tst_QMimeDatabase() +{ +} + void tst_QMimeDatabase::initTestCase() { + QVERIFY(m_temporaryDir.isValid()); + // Create a "global" and a "local" XDG data dir, right here. // The local dir will be empty initially, while the global dir will contain a copy of freedesktop.org.xml - QDir here = QDir::currentPath(); + const QDir here = QDir(m_temporaryDir.path()); - qputenv("XDG_DATA_DIRS", QFile::encodeName(here.absolutePath())); - QDir(here.absolutePath() + "/mime").removeRecursively(); - here.mkpath(QString::fromLatin1("mime/packages")); + m_globalXdgDir = m_temporaryDir.path() + QStringLiteral("/global"); + m_localXdgDir = m_temporaryDir.path() + QStringLiteral("/local"); - QFile xml(QFile::decodeName(SRCDIR "../../../src/mimetypes/mime/packages/freedesktop.org.xml")); - const QString mimeDir = here.absolutePath() + QLatin1String("/mime"); - xml.copy(mimeDir + QLatin1String("/packages/freedesktop.org.xml")); + const QString globalPackageDir = m_globalXdgDir + QStringLiteral("/mime/packages"); + QVERIFY(here.mkpath(globalPackageDir) && here.mkpath(m_localXdgDir)); - m_dataHome = here.absolutePath() + QLatin1String("/../datahome"); - qputenv("XDG_DATA_HOME", QFile::encodeName(m_dataHome)); - //qDebug() << "XDG_DATA_HOME=" << m_dataHome; + qputenv("XDG_DATA_DIRS", QFile::encodeName(m_globalXdgDir)); + qputenv("XDG_DATA_HOME", QFile::encodeName(m_localXdgDir)); + qDebug() << "\nLocal XDG_DATA_HOME: " << m_localXdgDir + << "\nGlobal XDG_DATA_DIRS: " << m_globalXdgDir; - // Make sure we start clean - cleanupTestCase(); -} + const QString freeDesktopXml = QStringLiteral("freedesktop.org.xml"); + const QString xmlFileName = QLatin1String(CORE_SOURCES) + + QStringLiteral("/mimetypes/mime/packages/") + + freeDesktopXml; + QVERIFY2(QFileInfo(xmlFileName).exists(), qPrintable(xmlFileName + QStringLiteral(" does not exist"))); + QFile xml(xmlFileName); + QVERIFY(xml.copy(globalPackageDir + '/' + freeDesktopXml)); -void tst_QMimeDatabase::cleanupTestCase() -{ - QDir here = QDir::currentPath(); - here.remove(QString::fromLatin1("mime/packages/yast2-metapackage-handler-mimetypes.xml")); + m_testSuite = QFINDTESTDATA("testfiles"); + if (m_testSuite.isEmpty()) + qWarning("%s", qPrintable(testSuiteWarning())); + + m_yastMimeTypes = QFINDTESTDATA(yastFileName); + QVERIFY2(!m_yastMimeTypes.isEmpty(), + qPrintable(QString::fromLatin1("Cannot find '%1' starting from '%2'"). + arg(yastFileName, QDir::currentPath()))); - QDir(m_dataHome).removeRecursively(); + init(); } void tst_QMimeDatabase::mimeTypeForName() @@ -173,6 +209,19 @@ void tst_QMimeDatabase::mimeTypeForFileName_data() QTest::newRow("doesn't exist but has known extension") << "IDontExist.txt" << "text/plain"; } +static inline QByteArray msgMimeTypeForFileNameFailed(const QList &actual, + const QString &expected) +{ + QByteArray result = "Actual ("; + foreach (const QMimeType &m, actual) { + result += m.name().toLocal8Bit(); + result += ' '; + } + result += ") , expected: "; + result += expected.toLocal8Bit(); + return result; +} + void tst_QMimeDatabase::mimeTypeForFileName() { QFETCH(QString, fileName); @@ -186,8 +235,8 @@ void tst_QMimeDatabase::mimeTypeForFileName() if (expectedMimeType == "application/octet-stream") { QVERIFY(mimes.isEmpty()); } else { - QVERIFY(!mimes.isEmpty()); - QCOMPARE(mimes.count(), 1); + QVERIFY2(!mimes.isEmpty(), msgMimeTypeForFileNameFailed(mimes, expectedMimeType).constData()); + QVERIFY2(mimes.count() == 1, msgMimeTypeForFileNameFailed(mimes, expectedMimeType).constData()); QCOMPARE(mimes.first().name(), expectedMimeType); } } @@ -549,20 +598,14 @@ void tst_QMimeDatabase::findByFileName_data() QTest::addColumn("mimeTypeName"); QTest::addColumn("xFail"); - QString prefix = QLatin1String(SRCDIR "testfiles/"); - - QFile f(prefix + QLatin1String("list")); - if (!f.open(QIODevice::ReadOnly)) { - const QString warning = QString::fromLatin1( - "Please download the shared-mime-info test suite:\n" - "cd tests/auto/corelib/mimetypes/qmimedatabase\n" - "wget http://cgit.freedesktop.org/xdg/shared-mime-info/snapshot/Release-1-0.zip\n" - "unzip Release-1-0.zip\n" - "ln -s Release-1-0/tests testfiles\n" - ); - qWarning() << warning; + if (m_testSuite.isEmpty()) QSKIP("shared-mime-info test suite not available."); - } + + const QString prefix = m_testSuite + QLatin1Char('/'); + const QString fileName = prefix + QLatin1String("list"); + QFile f(fileName); + QVERIFY2(f.open(QIODevice::ReadOnly|QIODevice::Text), + qPrintable(QString::fromLatin1("Cannot open %1: %2").arg(fileName, f.errorString()))); QByteArray line(1024, Qt::Uninitialized); @@ -582,7 +625,9 @@ void tst_QMimeDatabase::findByFileName_data() if (list.size() >= 3) xFail = list.at(2); - QTest::newRow(filePath.toLatin1().constData()) << QString(prefix + filePath) << mimeTypeType << xFail; + QTest::newRow(filePath.toLatin1().constData()) + << QString(prefix + filePath) + << mimeTypeType << xFail; } } @@ -717,13 +762,21 @@ void tst_QMimeDatabase::fromThreads() static bool runUpdateMimeDatabase(const QString &path) // TODO make it a QMimeDatabase method? { - const QString umd = QStandardPaths::findExecutable(QString::fromLatin1("update-mime-database")); - if (umd.isEmpty()) + const QString umdCommand = QString::fromLatin1("update-mime-database"); + const QString umd = QStandardPaths::findExecutable(umdCommand); + if (umd.isEmpty()) { + qWarning("%s does not exist.", qPrintable(umdCommand)); return false; + } QProcess proc; proc.setProcessChannelMode(QProcess::MergedChannels); // silence output - proc.start(umd, QStringList() << path); + proc.start(umd, QStringList(path)); + if (!proc.waitForStarted()) { + qWarning("Cannot start %s: %s", + qPrintable(umd), qPrintable(proc.errorString())); + return false; + } proc.waitForFinished(); //qDebug() << "runUpdateMimeDatabase" << path; return true; @@ -733,7 +786,7 @@ static bool waitAndRunUpdateMimeDatabase(const QString &path) { QFileInfo mimeCacheInfo(path + QString::fromLatin1("/mime.cache")); if (mimeCacheInfo.exists()) { - // Wait until the begining of the next second + // Wait until the beginning of the next second while (mimeCacheInfo.lastModified().secsTo(QDateTime::currentDateTime()) == 0) { QTest::qSleep(200); } @@ -767,16 +820,15 @@ void tst_QMimeDatabase::installNewGlobalMimeType() QMimeDatabase db; QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); - const QString fileName = QLatin1String("yast2-metapackage-handler-mimetypes.xml"); - const QString srcFile = QFile::decodeName(SRCDIR) + fileName; - - QDir here = QDir::currentPath(); - const QString mimeDir = here.absolutePath() + QLatin1String("/mime"); + const QString mimeDir = m_globalXdgDir + QLatin1String("/mime"); const QString destDir = mimeDir + QLatin1String("/packages/"); - const QString destFile = destDir + fileName; + const QString destFile = destDir + QLatin1String(yastFileName); QFile::remove(destFile); //qDebug() << destFile; - QVERIFY(QFile::copy(srcFile, destFile)); + + if (!QFileInfo(destDir).isDir()) + QVERIFY(QDir(m_globalXdgDir).mkpath(destDir)); + QVERIFY(QFile::copy(m_yastMimeTypes, destFile)); if (!waitAndRunUpdateMimeDatabase(mimeDir)) QSKIP("shared-mime-info not found, skipping mime.cache test"); @@ -801,16 +853,17 @@ void tst_QMimeDatabase::installNewLocalMimeType() QMimeDatabase db; QVERIFY(!db.mimeTypeForName(QLatin1String("text/x-suse-ymp")).isValid()); - const QString fileName = QLatin1String("yast2-metapackage-handler-mimetypes.xml"); - const QString srcFile = QFile::decodeName(SRCDIR) + fileName; - const QString mimeDir = m_dataHome + QLatin1String("/mime"); + const QString mimeDir = m_localXdgDir + QLatin1String("/mime"); const QString destDir = mimeDir + QLatin1String("/packages/"); QDir().mkpath(destDir); - const QString destFile = destDir + fileName; + const QString destFile = destDir + QLatin1String(yastFileName); QFile::remove(destFile); - QVERIFY(QFile::copy(srcFile, destFile)); - if (!runUpdateMimeDatabase(mimeDir)) - QSKIP("shared-mime-info not found, skipping mime.cache test");; + QVERIFY(QFile::copy(m_yastMimeTypes, destFile)); + if (!runUpdateMimeDatabase(mimeDir)) { + const QString skipWarning = QStringLiteral("shared-mime-info not found, skipping mime.cache test (") + + QDir::toNativeSeparators(mimeDir) + QLatin1Char(')'); + QSKIP(qPrintable(skipWarning)); + } QCOMPARE(db.mimeTypeForFile(QLatin1String("foo.ymu"), QMimeDatabase::MatchExtension).name(), QString::fromLatin1("text/x-suse-ymu")); diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h index 869990401c..94baf77ee9 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.h @@ -43,6 +43,7 @@ #define TST_QMIMEDATABASE_H #include +#include class tst_QMimeDatabase : public QObject { @@ -53,7 +54,6 @@ public: private slots: void initTestCase(); - void cleanupTestCase(); void mimeTypeForName(); void mimeTypeForFileName_data(); @@ -93,7 +93,13 @@ private slots: void installNewLocalMimeType(); private: - QString m_dataHome; + void init(); // test-specific + + QString m_globalXdgDir; + QString m_localXdgDir; + QString m_yastMimeTypes; + QTemporaryDir m_temporaryDir; + QString m_testSuite; }; #endif // TST_QMIMEDATABASE_H -- cgit v1.2.3 From 76afa1556c9739f341adf15226b84bcc8cbaa032 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Mon, 27 Feb 2012 22:19:39 +0100 Subject: Make QJsonPrivate::String compile on big endian platforms. Was missing a variable declaration and an explicit cast. Change-Id: I4f0fb9c3d9b8472adf0d91036442adc1fe255c7e Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 55c37988e2..0742ced39b 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -309,6 +309,7 @@ public: { d->length = str.length(); #if Q_BYTE_ORDER == Q_BIG_ENDIAN + const qle_ushort *uc = (const qle_ushort *)str.unicode(); for (int i = 0; i < str.length(); ++i) d->utf16[i] = uc[i]; #else @@ -359,7 +360,7 @@ public: QString str(l, Qt::Uninitialized); QChar *ch = str.data(); for (int i = 0; i < l; ++i) - ch[i] = d->utf16[i]; + ch[i] = QChar(d->utf16[i]); return str; #endif } -- cgit v1.2.3 From 3b80f1c4d582953da925e9f690a87a3af3158546 Mon Sep 17 00:00:00 2001 From: Jamie Kirkpatrick Date: Tue, 28 Feb 2012 16:22:49 +0100 Subject: Fix a double-release when loading NIB files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0c2c2a932b433a84e136da8e262739951a1d8c6e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 3a1f92fcf9..70e974161e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -93,7 +93,6 @@ void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader) // Load and instantiate nib file from temp NSURL *nibUrl = [NSURL fileURLWithPath : QCFString::toNSString(nibDir)]; - [nibUrl autorelease]; NSNib *nib = [[NSNib alloc] initWithContentsOfURL : nibUrl]; [nib autorelease]; if(!nib) { -- cgit v1.2.3 From eb4828bbfd54540b2b987bbae1cd6385e49c2a67 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 28 Feb 2012 09:34:20 +0100 Subject: Add operator<<(QTestData &, QStringBuilder) So this code still compiles with QStringBuilder QTest::newRow("foo") << foo + bar; Change-Id: Ie82a21c8fd07ec2d27ad85015aa1a0c4e94700d6 Reviewed-by: Jason McDonald --- src/testlib/qtestdata.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/testlib/qtestdata.h b/src/testlib/qtestdata.h index 22dae76167..8849b15ddb 100644 --- a/src/testlib/qtestdata.h +++ b/src/testlib/qtestdata.h @@ -89,6 +89,14 @@ inline QTestData &operator<<(QTestData &data, const char * value) return data; } +#ifdef QT_USE_QSTRINGBUILDER +template +inline QTestData &operator<<(QTestData &data, const QStringBuilder &value) +{ + return data << typename QConcatenable >::ConvertTo(value); +} +#endif + QT_END_NAMESPACE QT_END_HEADER -- cgit v1.2.3 From d87edf4e3e850d36c9d091b7bb62d9d0a481ad9f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 29 Feb 2012 12:28:03 +0200 Subject: Remove internal class QVolatileImage. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This made sense only for Symbian where there was a special CFbsBitmap-based backend present and it was used from the Symbian-specific VG and GL pixmap implementations. The generic version is merely a useless wrapper over QImage and is not in use anywhere in the codebase. Change-Id: I1dabe22dfb8cbbc35dce8e22703a3aff810fb5f9 Reviewed-by: Samuel Rødal Reviewed-by: Gunnar Sletta Reviewed-by: Lars Knoll --- src/gui/image/image.pri | 7 +- src/gui/image/qvolatileimage.cpp | 285 --------------------- src/gui/image/qvolatileimage_p.h | 100 -------- src/gui/image/qvolatileimagedata.cpp | 114 --------- src/gui/image/qvolatileimagedata_p.h | 84 ------ tests/auto/gui/image/image.pro | 1 - .../gui/image/qvolatileimage/qvolatileimage.pro | 6 - .../image/qvolatileimage/tst_qvolatileimage.cpp | 206 --------------- 8 files changed, 1 insertion(+), 802 deletions(-) delete mode 100644 src/gui/image/qvolatileimage.cpp delete mode 100644 src/gui/image/qvolatileimage_p.h delete mode 100644 src/gui/image/qvolatileimagedata.cpp delete mode 100644 src/gui/image/qvolatileimagedata_p.h delete mode 100644 tests/auto/gui/image/qvolatileimage/qvolatileimage.pro delete mode 100644 tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index f83e7e60c9..34a33aa0f0 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -23,8 +23,6 @@ HEADERS += \ image/qpixmapcache_p.h \ image/qplatformpixmap_qpa.h \ image/qimagepixmapcleanuphooks_p.h \ - image/qvolatileimage_p.h \ - image/qvolatileimagedata_p.h SOURCES += \ image/qbitmap.cpp \ @@ -42,13 +40,10 @@ SOURCES += \ image/qpixmap_raster.cpp \ image/qpixmap_blitter.cpp \ image/qnativeimage.cpp \ - image/qimagepixmapcleanuphooks.cpp \ - image/qvolatileimage.cpp + image/qimagepixmapcleanuphooks.cpp win32: SOURCES += image/qpixmap_win.cpp -SOURCES += image/qvolatileimagedata.cpp - # Built-in image format support HEADERS += \ image/qbmphandler_p.h \ diff --git a/src/gui/image/qvolatileimage.cpp b/src/gui/image/qvolatileimage.cpp deleted file mode 100644 index 8122c9cfe8..0000000000 --- a/src/gui/image/qvolatileimage.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qvolatileimage_p.h" -#include "qvolatileimagedata_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QVolatileImagePaintEnginePrivate : public QRasterPaintEnginePrivate -{ -public: - QVolatileImagePaintEnginePrivate() { } - QVolatileImage *img; -}; - -class QVolatileImagePaintEngine : public QRasterPaintEngine -{ - Q_DECLARE_PRIVATE(QVolatileImagePaintEngine) - -public: - QVolatileImagePaintEngine(QPaintDevice *device, QVolatileImage *img); - bool begin(QPaintDevice *device); - bool end(); - void drawPixmap(const QPointF &p, const QPixmap &pm); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); -}; - -QVolatileImage::QVolatileImage() - : d(new QVolatileImageData) -{ -} - -QVolatileImage::QVolatileImage(int w, int h, QImage::Format format) - : d(new QVolatileImageData(w, h, format)) -{ -} - -QVolatileImage::QVolatileImage(const QImage &sourceImage) - : d(new QVolatileImageData(sourceImage)) -{ -} - -QVolatileImage::QVolatileImage(void *nativeImage, void *nativeMask) - : d(new QVolatileImageData(nativeImage, nativeMask)) -{ -} - -// Need non-inline, non-autogenerated copy ctor, dtor, op= to keep the -// fwd declared QSharedData working. - -QVolatileImage::QVolatileImage(const QVolatileImage &other) - : d(other.d) -{ -} - -QVolatileImage::~QVolatileImage() -{ -} - -QVolatileImage &QVolatileImage::operator=(const QVolatileImage &rhs) -{ - d = rhs.d; - return *this; -} - -bool QVolatileImage::isNull() const -{ - return d->image.isNull(); -} - -QImage::Format QVolatileImage::format() const -{ - return d->image.format(); -} - -int QVolatileImage::width() const -{ - return d->image.width(); -} - -int QVolatileImage::height() const -{ - return d->image.height(); -} - -int QVolatileImage::bytesPerLine() const -{ - return d->image.bytesPerLine(); -} - -int QVolatileImage::byteCount() const -{ - return d->image.byteCount(); -} - -int QVolatileImage::depth() const -{ - return d->image.depth(); -} - -bool QVolatileImage::hasAlphaChannel() const -{ - return d->image.hasAlphaChannel(); -} - -void QVolatileImage::beginDataAccess() const -{ - d->beginDataAccess(); -} - -void QVolatileImage::endDataAccess(bool readOnly) const -{ - d->endDataAccess(readOnly); -} - -/*! - Access to pixel data via bits() or constBits() should be guarded by - begin/endDataAccess(). - */ -uchar *QVolatileImage::bits() -{ - return d->image.bits(); -} - -const uchar *QVolatileImage::constBits() const -{ - return d->image.constBits(); -} - -bool QVolatileImage::ensureFormat(QImage::Format format) -{ - return d->ensureFormat(format); -} - -/*! - This will always perform a copy of the pixel data. - */ -QImage QVolatileImage::toImage() const -{ - d->beginDataAccess(); - QImage newImage = d->image.copy(); // no sharing allowed - d->endDataAccess(true); - return newImage; -} - -/*! - Returns a reference to the image that is potentially using some native - buffer internally. Access to the image's pixel data should be guarded by - begin/endDataAccess(). Use it when there is a need for QImage APIs not provided - by this class. The returned QImage must never be shared or assigned to. - */ -QImage &QVolatileImage::imageRef() // non-const, in order to cause a detach -{ - d->ensureImage(); - return d->image; -} - -void *QVolatileImage::duplicateNativeImage() const -{ - return d->duplicateNativeImage(); -} - -void QVolatileImage::fill(uint pixelValue) -{ - beginDataAccess(); - imageRef().fill(pixelValue); - endDataAccess(); - d->ensureImage(); -} - -void QVolatileImage::copyFrom(QVolatileImage *source, const QRect &rect) -{ - if (source->isNull()) { - return; - } - QRect r = rect; - if (rect.isNull()) { - r = QRect(0, 0, source->width(), source->height()); - } - source->beginDataAccess(); - QImage &srcImgRef(source->imageRef()); - int srcbpl = srcImgRef.bytesPerLine(); - int srcbpp = srcImgRef.depth() / 8; - const uchar *sptr = srcImgRef.constBits() + r.y() * srcbpl; - beginDataAccess(); - QImage &dstImgRef(imageRef()); - int dstbpl = dstImgRef.bytesPerLine(); - uchar *dptr = dstImgRef.bits(); - for (int y = 0; y < r.height(); ++y) { - qMemCopy(dptr, sptr + r.x() * srcbpp, r.width() * srcbpp); - sptr += srcbpl; - dptr += dstbpl; - } - endDataAccess(); - source->endDataAccess(true); -} - -/*! - To be called from the PlatformPixmap's paintEngine(). - */ -QPaintEngine *QVolatileImage::paintEngine() -{ - if (!d->pengine) { - d->pengine = new QVolatileImagePaintEngine(&imageRef(), this); - } - return d->pengine; -} - -QVolatileImagePaintEngine::QVolatileImagePaintEngine(QPaintDevice *device, - QVolatileImage *img) - : QRasterPaintEngine(*(new QVolatileImagePaintEnginePrivate), device) -{ - Q_D(QVolatileImagePaintEngine); - d->img = img; -} - -bool QVolatileImagePaintEngine::begin(QPaintDevice *device) -{ - Q_D(QVolatileImagePaintEngine); - d->img->beginDataAccess(); - return QRasterPaintEngine::begin(device); -} - -bool QVolatileImagePaintEngine::end() -{ - Q_D(QVolatileImagePaintEngine); - bool ret = QRasterPaintEngine::end(); - d->img->endDataAccess(); - return ret; -} - -// For non-RasterClass pixmaps drawPixmap() would call toImage() which is slow in -// our case. Therefore drawPixmap() is rerouted to drawImage(). - -void QVolatileImagePaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) -{ - QRasterPaintEngine::drawPixmap(p, pm); -} - -void QVolatileImagePaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) -{ - QRasterPaintEngine::drawPixmap(r, pm, sr); -} - -QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimage_p.h b/src/gui/image/qvolatileimage_p.h deleted file mode 100644 index 808def7c32..0000000000 --- a/src/gui/image/qvolatileimage_p.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QVOLATILEIMAGE_P_H -#define QVOLATILEIMAGE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QVolatileImageData; - -class Q_GUI_EXPORT QVolatileImage -{ -public: - QVolatileImage(); - QVolatileImage(int w, int h, QImage::Format format); - explicit QVolatileImage(const QImage &sourceImage); - explicit QVolatileImage(void *nativeImage, void *nativeMask = 0); - QVolatileImage(const QVolatileImage &other); - ~QVolatileImage(); - QVolatileImage &operator=(const QVolatileImage &rhs); - - bool isNull() const; - QImage::Format format() const; - int width() const; - int height() const; - int bytesPerLine() const; - int byteCount() const; - int depth() const; - bool hasAlphaChannel() const; - void beginDataAccess() const; - void endDataAccess(bool readOnly = false) const; - uchar *bits(); - const uchar *constBits() const; - bool ensureFormat(QImage::Format format); - QImage toImage() const; - QImage &imageRef(); - QPaintEngine *paintEngine(); - void fill(uint pixelValue); - void *duplicateNativeImage() const; - void copyFrom(QVolatileImage *source, const QRect &rect); - -private: - QSharedDataPointer d; -}; - -QT_END_NAMESPACE - -#endif // QVOLATILEIMAGE_P_H diff --git a/src/gui/image/qvolatileimagedata.cpp b/src/gui/image/qvolatileimagedata.cpp deleted file mode 100644 index 3fcf24e187..0000000000 --- a/src/gui/image/qvolatileimagedata.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qvolatileimagedata_p.h" -#include - -QT_BEGIN_NAMESPACE - -QVolatileImageData::QVolatileImageData() - : pengine(0) -{ -} - -QVolatileImageData::QVolatileImageData(int w, int h, QImage::Format format) - : pengine(0) -{ - image = QImage(w, h, format); -} - -QVolatileImageData::QVolatileImageData(const QImage &sourceImage) - : pengine(0) -{ - image = sourceImage; -} - -QVolatileImageData::QVolatileImageData(void *, void *) - : pengine(0) -{ - // Not supported. -} - -QVolatileImageData::QVolatileImageData(const QVolatileImageData &other) - : QSharedData() -{ - image = other.image; - // The detach is not mandatory here but we do it nonetheless in order to - // keep the behavior consistent with other platforms. - image.detach(); - pengine = 0; -} - -QVolatileImageData::~QVolatileImageData() -{ - delete pengine; -} - -void QVolatileImageData::beginDataAccess() const -{ - // nothing to do here -} - -void QVolatileImageData::endDataAccess(bool readOnly) const -{ - Q_UNUSED(readOnly); - // nothing to do here -} - -bool QVolatileImageData::ensureFormat(QImage::Format format) -{ - if (image.format() != format) { - image = image.convertToFormat(format); - } - return true; -} - -void *QVolatileImageData::duplicateNativeImage() const -{ - return 0; -} - -void QVolatileImageData::ensureImage() -{ - // nothing to do here -} - -QT_END_NAMESPACE diff --git a/src/gui/image/qvolatileimagedata_p.h b/src/gui/image/qvolatileimagedata_p.h deleted file mode 100644 index 59e1be12e3..0000000000 --- a/src/gui/image/qvolatileimagedata_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QVOLATILEIMAGEDATA_P_H -#define QVOLATILEIMAGEDATA_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - - -QT_BEGIN_NAMESPACE - -class QVolatileImageData : public QSharedData -{ -public: - QVolatileImageData(); - QVolatileImageData(int w, int h, QImage::Format format); - QVolatileImageData(const QImage &sourceImage); - QVolatileImageData(void *nativeImage, void *nativeMask); - QVolatileImageData(const QVolatileImageData &other); - ~QVolatileImageData(); - - void beginDataAccess() const; - void endDataAccess(bool readOnly = false) const; - bool ensureFormat(QImage::Format format); - void *duplicateNativeImage() const; - void ensureImage(); - - QImage image; - QPaintEngine *pengine; -}; - -QT_END_NAMESPACE - -#endif // QVOLATILEIMAGEDATA_P_H diff --git a/tests/auto/gui/image/image.pro b/tests/auto/gui/image/image.pro index fe089f5e75..fa8f8df29d 100644 --- a/tests/auto/gui/image/image.pro +++ b/tests/auto/gui/image/image.pro @@ -9,7 +9,6 @@ SUBDIRS=\ qimageiohandler \ qimagewriter \ qmovie \ - qvolatileimage \ qicon \ qpicture \ diff --git a/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro b/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro deleted file mode 100644 index 3d982d7951..0000000000 --- a/tests/auto/gui/image/qvolatileimage/qvolatileimage.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qvolatileimage - -QT += gui-private widgets testlib - -SOURCES += tst_qvolatileimage.cpp diff --git a/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp b/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp deleted file mode 100644 index f203cfec0f..0000000000 --- a/tests/auto/gui/image/qvolatileimage/tst_qvolatileimage.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include -#include -#include -#include - -class tst_QVolatileImage : public QObject -{ - Q_OBJECT - -public: - tst_QVolatileImage() { } - -private slots: - void create(); - void ensureFormat(); - void dataAccess(); - void sharing(); - void fill(); - void copy(); -}; - -void tst_QVolatileImage::create() -{ - QVolatileImage nullImg; - QVERIFY(nullImg.isNull()); - - QVolatileImage img(100, 200, QImage::Format_ARGB32); - QVERIFY(!img.isNull()); - QCOMPARE(img.width(), 100); - QCOMPARE(img.height(), 200); - QCOMPARE(img.format(), QImage::Format_ARGB32); - QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); - QCOMPARE(img.hasAlphaChannel(), true); - QCOMPARE(img.depth(), 32); - - QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); - img = QVolatileImage(source); - QVERIFY(!img.isNull()); - QCOMPARE(img.width(), 12); - QCOMPARE(img.height(), 23); - QCOMPARE(img.format(), source.format()); - QCOMPARE(img.byteCount(), img.bytesPerLine() * img.height()); - QVERIFY(img.imageRef() == source); - QVERIFY(img.toImage() == source); - QCOMPARE(img.hasAlphaChannel(), true); - QCOMPARE(img.hasAlphaChannel(), img.imageRef().hasAlphaChannel()); - QCOMPARE(img.hasAlphaChannel(), img.toImage().hasAlphaChannel()); - QCOMPARE(img.depth(), 32); -} - -void tst_QVolatileImage::ensureFormat() -{ - QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); - QVolatileImage img(source); - QVERIFY(!img.isNull()); - QVERIFY(img.imageRef() == source); - QVERIFY(img.toImage() == source); - - QVERIFY(img.ensureFormat(QImage::Format_ARGB32_Premultiplied)); // no-op - QVERIFY(img.imageRef() == source); - QVERIFY(img.toImage() == source); - QVERIFY(img.format() == QImage::Format_ARGB32_Premultiplied); - - QVERIFY(img.ensureFormat(QImage::Format_RGB32)); // new data under-the-hood - QVERIFY(img.imageRef() != source); - QVERIFY(img.toImage() != source); - QVERIFY(img.format() == QImage::Format_RGB32); -} - -void tst_QVolatileImage::dataAccess() -{ - QImage source(12, 23, QImage::Format_ARGB32_Premultiplied); - QVolatileImage img(source); - QVERIFY(!img.isNull()); - img.beginDataAccess(); - QVERIFY(img.constBits()); - QVERIFY(img.imageRef().constBits()); - QVERIFY(img.bits()); - QVERIFY(img.imageRef().bits()); - img.endDataAccess(); - - img = QVolatileImage(12, 23, QImage::Format_ARGB32); - img.beginDataAccess(); - QVERIFY(img.constBits() && img.bits()); - img.endDataAccess(); -} - -void tst_QVolatileImage::sharing() -{ - QVolatileImage img1(100, 100, QImage::Format_ARGB32); - QVolatileImage img2 = img1; - img1.beginDataAccess(); - img2.beginDataAccess(); - QVERIFY(img1.constBits() == img2.constBits()); - img2.endDataAccess(); - img1.endDataAccess(); - img1.imageRef(); // non-const call, should detach - img1.beginDataAccess(); - img2.beginDataAccess(); - QVERIFY(img1.constBits() != img2.constBits()); - img2.endDataAccess(); - img1.endDataAccess(); - - // toImage() should return a copy of the internal QImage. - // imageRef() is a reference to the internal QImage. - QVERIFY(img1.imageRef().constBits() != img1.toImage().constBits()); -} - -bool fuzzyCompareImages(const QImage &image1, const QImage &image2, int tolerance) -{ - if (image1.bytesPerLine() != image2.bytesPerLine() - || image1.width() != image2.width() - || image1.height() != image2.height()) { - return false; - } - for (int i = 0; i < image1.height(); i++) { - const uchar *line1 = image1.scanLine(i); - const uchar *line2 = image2.scanLine(i); - int bytes = image1.bytesPerLine(); - for (int j = 0; j < bytes; j++) { - int delta = line1[j] - line2[j]; - if (qAbs(delta) > tolerance) - return false; - } - } - return true; -} - -void tst_QVolatileImage::fill() -{ - QVolatileImage img(100, 100, QImage::Format_ARGB32_Premultiplied); - QColor col = QColor(10, 20, 30); - img.fill(col.rgba()); - QVERIFY(img.imageRef().pixel(1, 1) == col.rgba()); - QVERIFY(img.toImage().pixel(1, 1) == col.rgba()); -} - -void tst_QVolatileImage::copy() -{ - QVolatileImage img(100, 100, QImage::Format_RGB32); - img.beginDataAccess(); - img.imageRef().fill(QColor(Qt::green).rgba()); - QPainter p(&img.imageRef()); - p.drawRect(10, 10, 50, 50); - p.end(); - img.endDataAccess(); - - QVolatileImage img2(100, 100, QImage::Format_RGB32); - img2.copyFrom(&img, QRect()); - QImage imgA = img.toImage(); - QImage imgB = img2.toImage(); - QCOMPARE(imgA.size(), imgB.size()); - QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); - - img2 = QVolatileImage(20, 20, QImage::Format_RGB32); - img2.copyFrom(&img, QRect(5, 5, 20, 20)); - imgA = img.toImage().copy(5, 5, 20, 20); - imgB = img2.toImage(); - QCOMPARE(imgA.size(), imgB.size()); - QVERIFY(fuzzyCompareImages(imgA, imgB, 0)); -} - -QTEST_MAIN(tst_QVolatileImage) -#include "tst_qvolatileimage.moc" -- cgit v1.2.3 From 56612a555d2b6e81239860cb457959dc8afdf274 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 17:00:04 +0100 Subject: Fix the include dir used by the CMake config files. I missed this one in 018e78575c6f7f5a90b41274468a26b09b909443 Change-Id: I194b96d2b1a64025ddb17fe2ed81566838555e13 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/create_cmake.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/create_cmake.prf b/mkspecs/features/create_cmake.prf index 1aa8ae5544..6a8045ab3b 100644 --- a/mkspecs/features/create_cmake.prf +++ b/mkspecs/features/create_cmake.prf @@ -24,7 +24,7 @@ CMAKE_PARTIAL_MODULE_DEPS = $$replace(CMAKE_MODULE_DEPS, ";", ";Qt5::") CMAKE_QT_INSTALL_PREFIX = $$replace($$list($$[QT_INSTALL_PREFIX]), \\\\, /)/ CMAKE_QT_INSTALL_PREFIX_ESCAPED = "^$$re_escape($$CMAKE_QT_INSTALL_PREFIX)" -CMAKE_INCLUDE_DIR = $$[QT_INSTALL_HEADERS] +CMAKE_INCLUDE_DIR = $$replace($$list($$[QT_INSTALL_HEADERS]), \\\\, /)/ contains(CMAKE_INCLUDE_DIR, "$${CMAKE_QT_INSTALL_PREFIX_ESCAPED}.*") { CMAKE_INCLUDE_DIR = $$replace(CMAKE_INCLUDE_DIR, "$$CMAKE_QT_INSTALL_PREFIX_ESCAPED", ) } else { -- cgit v1.2.3 From 7d5b0e2b042c5f6c3074cd20ba9baf9dfd733203 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Tue, 28 Feb 2012 14:53:42 +0000 Subject: network cookies: check "example.com" != "example.com." Only test code change, we already have the correct behaviour Task-number: QTBUG-20001 Change-Id: I2296f405f47f9c8d15796e69f9d1854063e38d6a Reviewed-by: Richard J. Moore --- .../access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index 0e046ad6f9..5dffe68386 100644 --- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -278,6 +278,8 @@ void tst_QNetworkCookieJar::cookiesForUrl_data() QTest::newRow("no-match-5") << allCookies << "http://qt.nokia.com" << result; QTest::newRow("no-match-6") << allCookies << "http://nokia.com/webinar" << result; QTest::newRow("no-match-7") << allCookies << "http://qt.nokia.com/webinar" << result; + QTest::newRow("no-match-8") << allCookies << "http://qt.nokia.com./web" << result; + QTest::newRow("no-match-9") << allCookies << "http://nokia.com./web" << result; result = allCookies; QTest::newRow("match-1") << allCookies << "http://nokia.com/web" << result; @@ -350,6 +352,16 @@ void tst_QNetworkCookieJar::cookiesForUrl_data() QTest::newRow("match-secure-1") << allCookies << "https://nokia.com/web" << result; QTest::newRow("match-secure-2") << allCookies << "https://qt.nokia.com/web" << result; + // domain ending in . + allCookies.clear(); + result.clear(); + QNetworkCookie cookieDot; + cookieDot.setDomain(".example.com."); + cookieDot.setName("a"); + allCookies += cookieDot; + QTest::newRow("no-match-domain-dot") << allCookies << "http://example.com" << result; + result += cookieDot; + QTest::newRow("match-domain-dot") << allCookies << "http://example.com." << result; } void tst_QNetworkCookieJar::cookiesForUrl() -- cgit v1.2.3 From 3f1a4be30263a676b7e188bf6cfa809c7788c87f Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 28 Feb 2012 15:46:01 +0100 Subject: Make loadAcquire const. Change-Id: Iad2d60d1abe363a3b85eaf152861d0979a997d81 Reviewed-by: Thiago Macieira --- src/corelib/arch/qatomic_gcc.h | 2 +- src/corelib/arch/qatomic_ia64.h | 4 ++-- src/corelib/thread/qbasicatomic.h | 4 ++-- src/corelib/thread/qgenericatomic.h | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corelib/arch/qatomic_gcc.h b/src/corelib/arch/qatomic_gcc.h index 225a7809eb..9edb74fa73 100644 --- a/src/corelib/arch/qatomic_gcc.h +++ b/src/corelib/arch/qatomic_gcc.h @@ -84,7 +84,7 @@ template struct QAtomicOps: QGenericAtomicOps > typedef T Type; #ifndef __ia64__ - static T loadAcquire(T &_q_value) + static T loadAcquire(const T &_q_value) { T tmp = _q_value; __sync_synchronize(); diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h index d82ad12223..5108751f2a 100644 --- a/src/corelib/arch/qatomic_ia64.h +++ b/src/corelib/arch/qatomic_ia64.h @@ -143,9 +143,9 @@ template struct QBasicAtomicOps: QGenericAtomicOps static inline - T loadAcquire(T &_q_value) + T loadAcquire(const T &_q_value) { - return *static_cast(&_q_value); + return *static_cast(&_q_value); } template static inline diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 96338c62dc..01a69dbd8b 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -136,7 +136,7 @@ public: // Atomic API, implemented in qatomic_XXX.h - T loadAcquire() { return Ops::loadAcquire(_q_value); } + T loadAcquire() const { return Ops::loadAcquire(_q_value); } void storeRelease(T newValue) { Ops::storeRelease(_q_value, newValue); } static bool isReferenceCountingNative() { return Ops::isReferenceCountingNative(); } @@ -206,7 +206,7 @@ public: void store(Type newValue) { _q_value = newValue; } // Atomic API, implemented in qatomic_XXX.h - Type loadAcquire() { return Ops::loadAcquire(_q_value); } + Type loadAcquire() const { return Ops::loadAcquire(_q_value); } void storeRelease(Type newValue) { Ops::storeRelease(_q_value, newValue); } static bool isTestAndSetNative() { return Ops::isTestAndSetNative(); } diff --git a/src/corelib/thread/qgenericatomic.h b/src/corelib/thread/qgenericatomic.h index f4d5e2f8d9..34c040c39b 100644 --- a/src/corelib/thread/qgenericatomic.h +++ b/src/corelib/thread/qgenericatomic.h @@ -85,7 +85,7 @@ template struct QGenericAtomicOps static void orderedMemoryFence() { } template static inline always_inline - T load(T &_q_value) + T load(const T &_q_value) { return _q_value; } @@ -97,9 +97,9 @@ template struct QGenericAtomicOps } template static inline always_inline - T loadAcquire(T &_q_value) + T loadAcquire(const T &_q_value) { - T tmp = *static_cast(&_q_value); + T tmp = *static_cast(&_q_value); BaseClass::acquireMemoryFence(); return tmp; } -- cgit v1.2.3 From 70784b9069fbd1c73eddbbfc83ffb44b2ca15854 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 29 Feb 2012 15:21:24 +0200 Subject: QFileSystemModel autotest fixes For some reason, hiding files via executing "attrib +h filename" process didn't work realiably, so changed the file hiding to be done via Windows native API. Also changed the test to use QTemporaryDir to simplify temporary directory handling a bit. Task-number: QTBUG-24291 Change-Id: I4f02b16e2f9105bcf5e6c5bf136f55434a26e2f4 Reviewed-by: Friedemann Kleint --- .../dialogs/qfilesystemmodel/qfilesystemmodel.pro | 2 - .../qfilesystemmodel/tst_qfilesystemmodel.cpp | 90 ++++++++-------------- 2 files changed, 33 insertions(+), 59 deletions(-) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro index 6e08e2d02b..166306757c 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro @@ -5,5 +5,3 @@ QT += core-private gui testlib SOURCES += tst_qfilesystemmodel.cpp TARGET = tst_qfilesystemmodel - -win32:CONFIG += insignificant_test # QTBUG-24291 diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 8724bf63c8..fe374b1e8d 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -51,6 +51,10 @@ #include #include #include +#include +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +# include // for SetFileAttributes +#endif #define WAITTIME 1000 @@ -69,13 +73,13 @@ class tst_QFileSystemModel : public QObject { public: tst_QFileSystemModel(); - virtual ~tst_QFileSystemModel(); public Q_SLOTS: void init(); void cleanup(); private slots: + void initTestCase(); void indexPath(); void rootPath(); @@ -122,29 +126,17 @@ private slots: void roleNames(); protected: - bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList(), const QString &baseDir = QDir::temp().absolutePath()); + bool createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount = 0, const QStringList &intial_dirs = QStringList()); private: QFileSystemModel *model; QString flatDirTestPath; + QTemporaryDir m_tempDir; }; tst_QFileSystemModel::tst_QFileSystemModel() : model(0) { qRegisterMetaType("QModelIndex"); - - QTime midnight(0, 0, 0); - qsrand(midnight.secsTo(QTime::currentTime())); - // generating unique temporary directory name - flatDirTestPath = QDir::temp().path() + '/' + QString("flatdirtest.") + QString::number(qrand()); -} - -tst_QFileSystemModel::~tst_QFileSystemModel() -{ - QString tmp = flatDirTestPath; - QDir dir(tmp); - if (dir.exists() && !dir.rmdir(tmp)) - qWarning("failed to remove tmp dir %s", dir.dirName().toAscii().data()); } void tst_QFileSystemModel::init() @@ -178,6 +170,12 @@ void tst_QFileSystemModel::cleanup() } } +void tst_QFileSystemModel::initTestCase() +{ + QVERIFY(m_tempDir.isValid()); + flatDirTestPath = m_tempDir.path(); +} + void tst_QFileSystemModel::indexPath() { #if !defined(Q_OS_WIN) @@ -367,15 +365,8 @@ void tst_QFileSystemModel::iconProvider() delete custom; } -bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs, const QString &dir) +bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringList &initial_files, int existingFileCount, const QStringList &initial_dirs) { - QDir baseDir(dir); - if (!baseDir.exists(test_path)) { - if (!baseDir.mkdir(test_path) && false) { - qDebug() << "failed to create dir" << test_path; - return false; - } - } //qDebug() << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files; TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount)); for (int i = 0; i < initial_dirs.count(); ++i) { @@ -406,8 +397,21 @@ bool tst_QFileSystemModel::createFiles(const QString &test_path, const QStringLi } file.close(); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - if (initial_files.at(i)[0] == '.') - QProcess::execute(QString("attrib +h %1").arg(file.fileName())); + if (initial_files.at(i)[0] == '.') { + QString hiddenFile = QDir::toNativeSeparators(file.fileName()); + wchar_t nativeHiddenFile[MAX_PATH]; + qMemSet(nativeHiddenFile, 0, sizeof(nativeHiddenFile)); + hiddenFile.toWCharArray(nativeHiddenFile); + DWORD currentAttributes = ::GetFileAttributes(nativeHiddenFile); + if (currentAttributes == 0xFFFFFFFF) { + qErrnoWarning("failed to get file attributes: %s", qPrintable(hiddenFile)); + return false; + } + if (!::SetFileAttributes(nativeHiddenFile, currentAttributes | FILE_ATTRIBUTE_HIDDEN)) { + qErrnoWarning("failed to set file hidden: %s", qPrintable(hiddenFile)); + return false; + } + } #endif //qDebug() << test_path + '/' + initial_files.at(i) << (QFile::exists(test_path + '/' + initial_files.at(i))); } @@ -818,16 +822,8 @@ void tst_QFileSystemModel::sort() myModel->d_func()->disableRecursiveSort = true; #endif - QDir dir(QDir::tempPath()); - //initialize the randomness - qsrand(QDateTime::currentDateTime().toTime_t()); - QString tempName = QLatin1String("sortTemp.") + QString::number(qrand()); - dir.mkdir(tempName); - dir.cd(tempName); - QTRY_VERIFY(dir.exists()); - + QDir dir(flatDirTestPath); const QString dirPath = dir.absolutePath(); - QVERIFY(dir.exists()); //Create a file that will be at the end when sorting by name (For Mac, the default) //but if we sort by size descending it will be the first @@ -889,14 +885,6 @@ void tst_QFileSystemModel::sort() delete tree; delete myModel; - - dir.setPath(QDir::tempPath()); - dir.cd(tempName); - tempFile.remove(); - tempFile2.remove(); - dir.cdUp(); - dir.rmdir(tempName); - } void tst_QFileSystemModel::mkdir() @@ -978,29 +966,17 @@ void tst_QFileSystemModel::drives() void tst_QFileSystemModel::dirsBeforeFiles() { - const QString dirPath = QString("%1/task221717_sortedOrder_test_dir").arg(QDir::tempPath()); - QDir dir(dirPath); - // clean up from last time - if (dir.exists()) { - for (int i = 0; i < 3; ++i) { - QLatin1Char c('a' + i); - dir.rmdir(QString("%1-dir").arg(c)); - QFile::remove(dirPath + QString("/%1-file").arg(c)); - } - dir.rmdir(dirPath); - } - QVERIFY(dir.mkpath(dirPath)); - QVERIFY(QDir(dirPath).exists()); + QDir dir(flatDirTestPath); for (int i = 0; i < 3; ++i) { QLatin1Char c('a' + i); dir.mkdir(QString("%1-dir").arg(c)); - QFile file(dirPath + QString("/%1-file").arg(c)); + QFile file(flatDirTestPath + QString("/%1-file").arg(c)); file.open(QIODevice::ReadWrite); file.close(); } - QModelIndex root = model->setRootPath(dirPath); + QModelIndex root = model->setRootPath(flatDirTestPath); QTest::qWait(1000); // allow model to be notified by the file system watcher // ensure that no file occurs before a directory -- cgit v1.2.3 From 3a72a1c7ed5adcdf3e473b50cc9c932e9290ee81 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 22 Feb 2012 10:58:28 +0100 Subject: Refactor the QPA dnd interface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Give QPlatformDrag a synchronous drag() function returning the Qt::DropAction - Move the base functionality for asynchronous event handling to the platformsupport library as QBasicDrag (extendable base class handling drag icon and providing new virtuals) and QSimpleDrag (sample implementation for drag within the Qt application). - Change the Windows implementation accordingly. - Change XCB to be based on QBasicDrag. - Clean up QDragManager. Change-Id: I654f76f0e55a385ba189bd74f3ceaded6a8fe318 Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/kernel.pri | 1 + src/gui/kernel/qdnd.cpp | 402 ++------------------- src/gui/kernel/qdnd_p.h | 87 +---- src/gui/kernel/qdrag.cpp | 89 +++-- src/gui/kernel/qdrag.h | 5 + src/gui/kernel/qevent.cpp | 5 +- src/gui/kernel/qguiapplication.cpp | 57 +-- src/gui/kernel/qguiapplication_p.h | 6 +- src/gui/kernel/qplatformdrag_qpa.cpp | 187 ++++++++++ src/gui/kernel/qplatformdrag_qpa.h | 49 ++- src/gui/kernel/qwindowsysteminterface_qpa.cpp | 9 +- src/gui/kernel/qwindowsysteminterface_qpa.h | 6 +- src/platformsupport/dnd/dnd.pri | 6 +- src/platformsupport/dnd/qshapedpixmapdndwindow.cpp | 100 +++++ src/platformsupport/dnd/qshapedpixmapdndwindow_p.h | 78 ++++ src/platformsupport/dnd/qsimpledrag.cpp | 318 +++++++++++----- src/platformsupport/dnd/qsimpledrag_p.h | 64 +++- src/plugins/platforms/windows/qwindowsdrag.cpp | 278 +++++--------- src/plugins/platforms/windows/qwindowsdrag.h | 14 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 4 +- src/plugins/platforms/xcb/qxcbdrag.cpp | 396 ++++++++------------ src/plugins/platforms/xcb/qxcbdrag.h | 45 ++- src/plugins/platforms/xcb/qxcbwindow.cpp | 6 +- src/widgets/itemviews/qitemdelegate.cpp | 6 +- src/widgets/itemviews/qstyleditemdelegate.cpp | 6 +- 25 files changed, 1154 insertions(+), 1070 deletions(-) create mode 100644 src/gui/kernel/qplatformdrag_qpa.cpp create mode 100644 src/platformsupport/dnd/qshapedpixmapdndwindow.cpp create mode 100644 src/platformsupport/dnd/qshapedpixmapdndwindow_p.h diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 9c5f3b10da..2656d8ffdb 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -66,6 +66,7 @@ SOURCES += \ kernel/qwindowsysteminterface_qpa.cpp \ kernel/qplatforminputcontext_qpa.cpp \ kernel/qplatformintegration_qpa.cpp \ + kernel/qplatformdrag_qpa.cpp \ kernel/qplatformscreen_qpa.cpp \ kernel/qplatformintegrationfactory_qpa.cpp \ kernel/qplatformintegrationplugin_qpa.cpp \ diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp index 2fb250cf18..1ed4a96192 100644 --- a/src/gui/kernel/qdnd.cpp +++ b/src/gui/kernel/qdnd.cpp @@ -125,417 +125,79 @@ QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies) #endif // the universe's only drag manager -QDragManager *QDragManager::instance = 0; +QDragManager *QDragManager::m_instance = 0; QDragManager::QDragManager() - : QObject(qApp) + : QObject(qApp), m_platformDropData(0), m_currentDropTarget(0), + m_platformDrag(QGuiApplicationPrivate::platformIntegration()->drag()), + m_object(0) { - Q_ASSERT(!instance); + Q_ASSERT(!m_instance); - object = 0; - beingCancelled = false; - restoreCursor = false; - willDrop = false; - eventLoop = 0; - currentDropTarget = 0; - shapedPixmapWindow = 0; - - possible_actions = Qt::IgnoreAction; - - QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); - platformDrag = pi->drag(); - - platformDropData = 0; - if (platformDrag) - platformDropData = platformDrag->platformDropData(); + if (m_platformDrag) + m_platformDropData = m_platformDrag->platformDropData(); } QDragManager::~QDragManager() { -#ifndef QT_NO_CURSOR - if (restoreCursor) - QGuiApplication::restoreOverrideCursor(); -#endif - instance = 0; + m_instance = 0; } QDragManager *QDragManager::self() { - if (!instance && !QGuiApplication::closingDown()) - instance = new QDragManager; - return instance; + if (!m_instance && !QGuiApplication::closingDown()) + m_instance = new QDragManager; + return m_instance; } -QPixmap QDragManager::dragCursor(Qt::DropAction action) const +QObject *QDragManager::source() const { - typedef QMap::const_iterator Iterator; - - if (const QDragPrivate *d = dragPrivate()) { - const Iterator it = d->customCursors.constFind(action); - if (it != d->customCursors.constEnd()) - return it.value(); - } - - Qt::CursorShape shape = Qt::ForbiddenCursor; - switch (action) { - case Qt::MoveAction: - shape = Qt::DragMoveCursor; - break; - case Qt::CopyAction: - shape = Qt::DragCopyCursor; - break; - case Qt::LinkAction: - shape = Qt::DragLinkCursor; - break; - default: - shape = Qt::ForbiddenCursor; - } - return QGuiApplicationPrivate::instance()->getPixmapCursor(shape); -} - -Qt::DropAction QDragManager::defaultAction(Qt::DropActions possibleActions, - Qt::KeyboardModifiers modifiers) const -{ -#ifdef QDND_DEBUG - qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)"); - qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1()); -#endif - - QDragPrivate *d = dragPrivate(); - Qt::DropAction defaultAction = d ? d->defaultDropAction : Qt::IgnoreAction; - - if (defaultAction == Qt::IgnoreAction) { - //This means that the drag was initiated by QDrag::start and we need to - //preserve the old behavior - defaultAction = Qt::CopyAction; - } - - if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) - defaultAction = Qt::LinkAction; - else if (modifiers & Qt::ControlModifier) - defaultAction = Qt::CopyAction; - else if (modifiers & Qt::ShiftModifier) - defaultAction = Qt::MoveAction; - else if (modifiers & Qt::AltModifier) - defaultAction = Qt::LinkAction; - -#ifdef QDND_DEBUG - qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1()); -#endif - - // Check if the action determined is allowed - if (!(possibleActions & defaultAction)) { - if (possibleActions & Qt::CopyAction) - defaultAction = Qt::CopyAction; - else if (possibleActions & Qt::MoveAction) - defaultAction = Qt::MoveAction; - else if (possibleActions & Qt::LinkAction) - defaultAction = Qt::LinkAction; - else - defaultAction = Qt::IgnoreAction; - } - -#ifdef QDND_DEBUG - qDebug("default action : %s", dragActionsToString(defaultAction).latin1()); -#endif - - return defaultAction; + if (m_object) + return m_object->source(); + return 0; } void QDragManager::setCurrentTarget(QObject *target, bool dropped) { - if (currentDropTarget == target) + if (m_currentDropTarget == target) return; - currentDropTarget = target; - if (!dropped && object) { - object->d_func()->target = target; - emit object->targetChanged(target); + m_currentDropTarget = target; + if (!dropped && m_object) { + m_object->d_func()->target = target; + emit m_object->targetChanged(target); } - } -QObject *QDragManager::currentTarget() +QObject *QDragManager::currentTarget() const { - return currentDropTarget; -} - - -static const int default_pm_hotx = -2; -static const int default_pm_hoty = -16; -static const char *const default_pm[] = { -"13 9 3 1", -". c None", -" c #000000", -"X c #FFFFFF", -"X X X X X X X", -" X X X X X X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X.........X ", -"X ......... X", -" X X X X X X ", -"X X X X X X X", -}; - - -QShapedPixmapWindow::QShapedPixmapWindow() - : QWindow() -{ - setSurfaceType(RasterSurface); - setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | - Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput); - create(); - backingStore = new QBackingStore(this); -} - -void QShapedPixmapWindow::render() -{ - QRect rect(QPoint(), geometry().size()); - backingStore->resize(rect.size()); - - backingStore->beginPaint(rect); - - QPaintDevice *device = backingStore->paintDevice(); - - { - QPainter p(device); - p.drawPixmap(0, 0, pixmap); - } - - backingStore->endPaint(); - backingStore->flush(rect); -} - - - - -static Qt::KeyboardModifiers oldstate; - -void QDragManager::updatePixmap() -{ - if (shapedPixmapWindow) { - shapedPixmapWindow->pixmap = QPixmap(); - shapedPixmapWindow->hotSpot = QPoint(default_pm_hotx,default_pm_hoty); - if (object) { - shapedPixmapWindow->pixmap = object->pixmap(); - if (!shapedPixmapWindow->pixmap.isNull()) - shapedPixmapWindow->hotSpot = object->hotSpot(); - } - if (shapedPixmapWindow->pixmap.isNull()) - shapedPixmapWindow->pixmap = QPixmap(default_pm); - shapedPixmapWindow->setGeometry(QRect(QCursor::pos() - shapedPixmapWindow->hotSpot, shapedPixmapWindow->pixmap.size())); - shapedPixmapWindow->show(); - shapedPixmapWindow->render(); - } -} - -void QDragManager::updateCursor() -{ - if (shapedPixmapWindow) { - shapedPixmapWindow->render(); // ### Hack - shapedPixmapWindow->move(QCursor::pos() - shapedPixmapWindow->hotSpot); - } - - Qt::CursorShape cursorShape = Qt::ForbiddenCursor; - if (willDrop) { - if (global_accepted_action == Qt::CopyAction) { - cursorShape = Qt::DragCopyCursor; - } else if (global_accepted_action == Qt::LinkAction) { - cursorShape = Qt::DragLinkCursor; - } else { - cursorShape = Qt::DragMoveCursor; - } - } - QCursor *cursor = qApp->overrideCursor(); - if (cursor && cursorShape != cursor->shape()) - qApp->changeOverrideCursor(QCursor(cursorShape)); -} - - -bool QDragManager::eventFilter(QObject *o, QEvent *e) -{ - if (beingCancelled) { - if (e->type() == QEvent::KeyRelease && static_cast(e)->key() == Qt::Key_Escape) { - qApp->removeEventFilter(this); - Q_ASSERT(object == 0); - beingCancelled = false; - eventLoop->exit(); - return true; // block the key release - } - return false; - } - - Q_ASSERT(object != 0); - - if (!qobject_cast(o)) - return false; - - switch(e->type()) { - case QEvent::ShortcutOverride: - // prevent accelerators from firing while dragging - e->accept(); - return true; - - case QEvent::KeyPress: - case QEvent::KeyRelease: - { - QKeyEvent *ke = static_cast(e); - if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - eventLoop->exit(); - } else { - // ### x11 forces move! - updateCursor(); - } - return true; // Eat all key events - } - - case QEvent::MouseMove: - move(static_cast(e)); - return true; // Eat all mouse events - - case QEvent::MouseButtonRelease: - qApp->removeEventFilter(this); - if (willDrop) - drop(static_cast(e)); - else - cancel(); - beingCancelled = false; - eventLoop->exit(); - return true; // Eat all mouse events - - case QEvent::MouseButtonPress: - case QEvent::MouseButtonDblClick: - case QEvent::Wheel: - return true; - default: - break; - } - return false; + return m_currentDropTarget; } Qt::DropAction QDragManager::drag(QDrag *o) { - if (!o || object == o) + if (!o || m_object == o) return Qt::IgnoreAction; - if (!platformDrag || !o->source()) { + if (!m_platformDrag || !o->source()) { o->deleteLater(); return Qt::IgnoreAction; } - if (object) { - cancel(); - qApp->removeEventFilter(this); - beingCancelled = false; - } - - object = o; - if (!shapedPixmapWindow) - shapedPixmapWindow = new QShapedPixmapWindow(); - oldstate = Qt::NoModifier; // #### Should use state that caused the drag -// drag_mode = mode; - - possible_actions = dragPrivate()->possible_actions; - - willDrop = false; - object->d_func()->target = 0; - qApp->installEventFilter(this); - - global_accepted_action = Qt::CopyAction; -#ifndef QT_NO_CURSOR - qApp->setOverrideCursor(Qt::DragCopyCursor); - restoreCursor = true; - updateCursor(); -#endif - updatePixmap(); - - platformDrag->startDrag(); - - eventLoop = new QEventLoop; - (void) eventLoop->exec(); - delete eventLoop; - eventLoop = 0; - - delete shapedPixmapWindow; - shapedPixmapWindow = 0; - - return global_accepted_action; -} - -void QDragManager::move(const QMouseEvent *me) -{ - if (!platformDrag) - return; - - platformDrag->move(me); -} - -void QDragManager::drop(const QMouseEvent *me) -{ - if (!platformDrag) - return; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QGuiApplication::restoreOverrideCursor(); - restoreCursor = false; - } -#endif - willDrop = false; - - platformDrag->drop(me); - - if (object) - object->deleteLater(); - object = 0; -} - -void QDragManager::cancel(bool deleteSource) -{ - if (!platformDrag) - return; - -#ifndef QT_NO_CURSOR - if (restoreCursor) { - QGuiApplication::restoreOverrideCursor(); - restoreCursor = false; + if (m_object) { + qWarning("QDragManager::drag in possibly invalid state"); + return Qt::IgnoreAction; } -#endif - - beingCancelled = true; - platformDrag->cancel(); + m_object = o; - if (object && deleteSource) - object->deleteLater(); - object = 0; + m_object->d_func()->target = 0; - global_accepted_action = Qt::IgnoreAction; -} - -/*! - Called from startDrag() in QPlatformDrag implementations that do not need - the desktop-oriented stuff provided by the event filter (e.g. because their - drag is not based on mouse events). Instead, they will manage everything on - their own, will not rely on move/drop/cancel, and will call stopDrag() to stop - the event loop when the drag is over. - */ -void QDragManager::unmanageEvents() -{ - qApp->removeEventFilter(this); -} - -void QDragManager::stopDrag() -{ - if (eventLoop) - eventLoop->exit(); + const Qt::DropAction result = m_platformDrag->drag(m_object); + m_object = 0; + return result; } #endif // QT_NO_DRAGANDDROP diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 857be34d10..764b73c06f 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -98,100 +98,45 @@ protected: class QDragPrivate : public QObjectPrivate { public: + QDragPrivate() + : source(0) + , target(0) + , data(0) + { } QObject *source; QObject *target; QMimeData *data; QPixmap pixmap; QPoint hotspot; - Qt::DropActions possible_actions; Qt::DropAction executed_action; + Qt::DropActions supported_actions; + Qt::DropAction default_action; QMap customCursors; - Qt::DropAction defaultDropAction; }; -class QShapedPixmapWindow : public QWindow -{ -public: - QShapedPixmapWindow(); - - void exposeEvent(QExposeEvent *) - { - render(); - } - - void render(); - - QBackingStore *backingStore; - QPixmap pixmap; - QPoint hotSpot; -}; - - class Q_GUI_EXPORT QDragManager : public QObject { Q_OBJECT - // only friend classes can use QDragManager. - friend class QDrag; - friend class QDragMoveEvent; - friend class QDropEvent; - friend class QApplication; - - bool eventFilter(QObject *, QEvent *); - public: QDragManager(); ~QDragManager(); static QDragManager *self(); - virtual Qt::DropAction drag(QDrag *); - - virtual void cancel(bool deleteSource = true); - virtual void move(const QMouseEvent *me); - virtual void drop(const QMouseEvent *me); - - void updatePixmap(); - void updateCursor(); - - Qt::DropAction defaultAction(Qt::DropActions possibleActions, - Qt::KeyboardModifiers modifiers) const; - - QPixmap dragCursor(Qt::DropAction action) const; - - QDragPrivate *dragPrivate() const { return object ? object->d_func() : 0; } - - inline QMimeData *dropData() - { return object ? dragPrivate()->data : platformDropData; } - - void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); } + Qt::DropAction drag(QDrag *); void setCurrentTarget(QObject *target, bool dropped = false); - QObject *currentTarget(); + QObject *currentTarget() const; - QDrag *object; - - bool beingCancelled; - bool restoreCursor; - bool willDrop; - QEventLoop *eventLoop; - - Qt::DropActions possible_actions; - // Shift/Ctrl handling, and final drop status - Qt::DropAction global_accepted_action; - - QShapedPixmapWindow *shapedPixmapWindow; - - void unmanageEvents(); - void stopDrag(); + QDrag *object() const { return m_object; } + QObject *source() const; private: - QMimeData *platformDropData; - - Qt::DropAction currentActionForOverrideCursor; - QObject *currentDropTarget; - - QPlatformDrag *platformDrag; + QMimeData *m_platformDropData; + QObject *m_currentDropTarget; + QPlatformDrag *m_platformDrag; + QDrag *m_object; - static QDragManager *instance; + static QDragManager *m_instance; Q_DISABLE_COPY(QDragManager) }; diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp index 694b12a180..ead0805bd1 100644 --- a/src/gui/kernel/qdrag.cpp +++ b/src/gui/kernel/qdrag.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include +#include "private/qguiapplication_p.h" #include #include #include "qdnd_p.h" @@ -114,9 +115,9 @@ QDrag::QDrag(QObject *dragSource) d->target = 0; d->data = 0; d->hotspot = QPoint(-10, -10); - d->possible_actions = Qt::CopyAction; d->executed_action = Qt::IgnoreAction; - d->defaultDropAction = Qt::IgnoreAction; + d->supported_actions = Qt::IgnoreAction; + d->default_action = Qt::IgnoreAction; } /*! @@ -126,9 +127,6 @@ QDrag::~QDrag() { Q_D(QDrag); delete d->data; - QDragManager *manager = QDragManager::self(); - if (manager && manager->object == this) - manager->cancel(false); } /*! @@ -264,24 +262,22 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defa qWarning("QDrag: No mimedata set before starting the drag"); return d->executed_action; } - QDragManager *manager = QDragManager::self(); - d->defaultDropAction = Qt::IgnoreAction; - d->possible_actions = supportedActions; - - if (manager) { - if (defaultDropAction == Qt::IgnoreAction) { - if (supportedActions & Qt::MoveAction) { - d->defaultDropAction = Qt::MoveAction; - } else if (supportedActions & Qt::CopyAction) { - d->defaultDropAction = Qt::CopyAction; - } else if (supportedActions & Qt::LinkAction) { - d->defaultDropAction = Qt::LinkAction; - } - } else { - d->defaultDropAction = defaultDropAction; + Qt::DropAction transformedDefaultDropAction = Qt::IgnoreAction; + + if (defaultDropAction == Qt::IgnoreAction) { + if (supportedActions & Qt::MoveAction) { + transformedDefaultDropAction = Qt::MoveAction; + } else if (supportedActions & Qt::CopyAction) { + transformedDefaultDropAction = Qt::CopyAction; + } else if (supportedActions & Qt::LinkAction) { + transformedDefaultDropAction = Qt::LinkAction; } - d->executed_action = manager->drag(this); + } else { + transformedDefaultDropAction = defaultDropAction; } + d->supported_actions = supportedActions; + d->default_action = transformedDefaultDropAction; + d->executed_action = QDragManager::self()->drag(this); return d->executed_action; } @@ -308,11 +304,9 @@ Qt::DropAction QDrag::start(Qt::DropActions request) qWarning("QDrag: No mimedata set before starting the drag"); return d->executed_action; } - QDragManager *manager = QDragManager::self(); - d->defaultDropAction = Qt::IgnoreAction; - d->possible_actions = request | Qt::CopyAction; - if (manager) - d->executed_action = manager->drag(this); + d->supported_actions = request | Qt::CopyAction; + d->default_action = Qt::IgnoreAction; + d->executed_action = QDragManager::self()->drag(this); return d->executed_action; } @@ -335,6 +329,49 @@ void QDrag::setDragCursor(const QPixmap &cursor, Qt::DropAction action) d->customCursors[action] = cursor; } +/*! + Returns the drag cursor for the \a action. + + \since 5.0 +*/ + +QPixmap QDrag::dragCursor(Qt::DropAction action) const +{ + typedef QMap::const_iterator Iterator; + + Q_D(const QDrag); + const Iterator it = d->customCursors.constFind(action); + if (it != d->customCursors.constEnd()) + return it.value(); + + Qt::CursorShape shape = Qt::ForbiddenCursor; + switch (action) { + case Qt::MoveAction: + shape = Qt::DragMoveCursor; + break; + case Qt::CopyAction: + shape = Qt::DragCopyCursor; + break; + case Qt::LinkAction: + shape = Qt::DragLinkCursor; + break; + default: + shape = Qt::ForbiddenCursor; + } + return QGuiApplicationPrivate::instance()->getPixmapCursor(shape); +} + +Qt::DropActions QDrag::supportedActions() const +{ + Q_D(const QDrag); + return d->supported_actions; +} + +Qt::DropAction QDrag::defaultAction() const +{ + Q_D(const QDrag); + return d->default_action; +} /*! \fn void QDrag::actionChanged(Qt::DropAction action) diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h index 0a1ddff2d9..de84b6588b 100644 --- a/src/gui/kernel/qdrag.h +++ b/src/gui/kernel/qdrag.h @@ -56,6 +56,7 @@ class QPixmap; class QPoint; class QDragManager; + class Q_GUI_EXPORT QDrag : public QObject { Q_OBJECT @@ -81,6 +82,10 @@ public: Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction); void setDragCursor(const QPixmap &cursor, Qt::DropAction action); + QPixmap dragCursor(Qt::DropAction action) const; + + Qt::DropActions supportedActions() const; + Qt::DropAction defaultAction() const; Q_SIGNALS: void actionChanged(Qt::DropAction action); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 281d4f61bc..ee121f2071 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2295,8 +2295,9 @@ QDropEvent::~QDropEvent() */ QObject* QDropEvent::source() const { - QDragManager *manager = QDragManager::self(); - return (manager && manager->object) ? manager->object->source() : 0; + if (const QDragManager *manager = QDragManager::self()) + return manager->source(); + return 0; } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 1cd448a6bb..09d4e98c3c 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -73,8 +73,11 @@ #include "private/qwindowsysteminterface_qpa_p.h" #include "private/qwindow_p.h" #include "private/qcursor_p.h" + #include "private/qdnd_p.h" #include +#include "qplatformdrag_qpa.h" + #ifndef QT_NO_CURSOR #include "qplatformcursor_qpa.h" #endif @@ -326,8 +329,7 @@ QGuiApplication::QGuiApplication(int &argc, char **argv, int flags) QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p) : QCoreApplication(p) { - d_func()->init(); -} + d_func()->init(); } /*! Destructs the application. @@ -1547,49 +1549,62 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E QCoreApplication::sendSpontaneousEvent(window, &exposeEvent); } -Qt::DropAction QGuiApplicationPrivate::processDrag(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { static QPointer currentDragWindow; - QDragManager *manager = QDragManager::self(); + static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; + QPlatformDrag *platformDrag = platformIntegration()->drag(); + if (!platformDrag) { + lastAcceptedDropAction = Qt::IgnoreAction; + return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); + } + if (!dropData) { if (currentDragWindow.data() == w) currentDragWindow = 0; QDragLeaveEvent e; QGuiApplication::sendEvent(w, &e); - manager->global_accepted_action = Qt::IgnoreAction; - return Qt::IgnoreAction; + lastAcceptedDropAction = Qt::IgnoreAction; + return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } - QDragMoveEvent me(p, manager->possible_actions, dropData, + QDragMoveEvent me(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + if (w != currentDragWindow) { + lastAcceptedDropAction = Qt::IgnoreAction; if (currentDragWindow) { QDragLeaveEvent e; QGuiApplication::sendEvent(currentDragWindow, &e); - manager->global_accepted_action = Qt::IgnoreAction; } currentDragWindow = w; - QDragEnterEvent e(p, manager->possible_actions, dropData, + QDragEnterEvent e(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); QGuiApplication::sendEvent(w, &e); - manager->global_accepted_action = e.isAccepted() ? e.dropAction() : Qt::IgnoreAction; - if (manager->global_accepted_action != Qt::IgnoreAction) { - me.setDropAction(manager->global_accepted_action); - me.accept(); - } + if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction) + lastAcceptedDropAction = e.dropAction(); + } + + // Handling 'DragEnter' should suffice for the application. + if (lastAcceptedDropAction != Qt::IgnoreAction + && (supportedActions & lastAcceptedDropAction)) { + me.setDropAction(lastAcceptedDropAction); + me.accept(); } QGuiApplication::sendEvent(w, &me); - manager->global_accepted_action = me.isAccepted() ? me.dropAction() : Qt::IgnoreAction; - return manager->global_accepted_action; + lastAcceptedDropAction = me.isAccepted() ? + me.dropAction() : Qt::IgnoreAction; + return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect()); } -Qt::DropAction QGuiApplicationPrivate::processDrop(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - QDragManager *manager = QDragManager::self(); - QDropEvent de(p, manager->possible_actions, dropData, + QDropEvent de(p, supportedActions, dropData, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); QGuiApplication::sendEvent(w, &de); - manager->global_accepted_action = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; - return manager->global_accepted_action; + + Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; + QPlatformDropQtResponse response(de.isAccepted(),acceptedAction); + return response; } #ifndef QT_NO_CLIPBOARD diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 68546ce0cf..d9477a3e9e 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -53,6 +53,8 @@ #include "private/qwindowsysteminterface_qpa_p.h" #include "private/qshortcutmap_p.h" +#include "qplatformdrag_qpa.h" + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -121,8 +123,8 @@ public: static void processExposeEvent(QWindowSystemInterfacePrivate::ExposeEvent *e); - static Qt::DropAction processDrag(QWindow *w, QMimeData *dropData, const QPoint &p); - static Qt::DropAction processDrop(QWindow *w, QMimeData *dropData, const QPoint &p); + static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); + static QPlatformDropQtResponse processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); static bool processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); diff --git a/src/gui/kernel/qplatformdrag_qpa.cpp b/src/gui/kernel/qplatformdrag_qpa.cpp new file mode 100644 index 0000000000..832b91db7e --- /dev/null +++ b/src/gui/kernel/qplatformdrag_qpa.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdrag_qpa.h" + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QPlatformDropQtResponse::QPlatformDropQtResponse(bool accepted, Qt::DropAction acceptedAction) + : m_accepted(accepted) + , m_accepted_action(acceptedAction) +{ +} + +bool QPlatformDropQtResponse::isAccepted() const +{ + return m_accepted; +} + +Qt::DropAction QPlatformDropQtResponse::acceptedAction() const +{ + return m_accepted_action; +} + +QPlatformDragQtResponse::QPlatformDragQtResponse(bool accepted, Qt::DropAction acceptedAction, QRect answerRect) + : QPlatformDropQtResponse(accepted,acceptedAction) + , m_answer_rect(answerRect) +{ +} + +QRect QPlatformDragQtResponse::answerRect() const +{ + return m_answer_rect; +} + +class QPlatformDragPrivate { +public: + QPlatformDragPrivate() : cursor_drop_action(Qt::IgnoreAction) {} + + Qt::DropAction cursor_drop_action; +}; + +QPlatformDrag::QPlatformDrag() : d_ptr(new QPlatformDragPrivate) +{ +} + +QPlatformDrag::~QPlatformDrag() +{ +} + +QDrag *QPlatformDrag::currentDrag() const +{ + return QDragManager::self()->object(); +} + +Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, + Qt::KeyboardModifiers modifiers) const +{ +#ifdef QDND_DEBUG + qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)"); + qDebug("keyboard modifiers : %s", KeyboardModifiersToString(modifiers).latin1()); +#endif + + Qt::DropAction default_action = Qt::IgnoreAction; + + if (currentDrag()) { + default_action = currentDrag()->defaultAction(); + } + + + if (default_action == Qt::IgnoreAction) { + //This means that the drag was initiated by QDrag::start and we need to + //preserve the old behavior + default_action = Qt::CopyAction; + } + + if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) + default_action = Qt::LinkAction; + else if (modifiers & Qt::ControlModifier) + default_action = Qt::CopyAction; + else if (modifiers & Qt::ShiftModifier) + default_action = Qt::MoveAction; + else if (modifiers & Qt::AltModifier) + default_action = Qt::LinkAction; + +#ifdef QDND_DEBUG + qDebug("possible actions : %s", dragActionsToString(possibleActions).latin1()); +#endif + + // Check if the action determined is allowed + if (!(possibleActions & default_action)) { + if (possibleActions & Qt::CopyAction) + default_action = Qt::CopyAction; + else if (possibleActions & Qt::MoveAction) + default_action = Qt::MoveAction; + else if (possibleActions & Qt::LinkAction) + default_action = Qt::LinkAction; + else + default_action = Qt::IgnoreAction; + } + +#ifdef QDND_DEBUG + qDebug("default action : %s", dragActionsToString(defaultAction).latin1()); +#endif + + return default_action; +} + +/*! + \brief Called to notify QDrag about changes of the current action. + */ + +void QPlatformDrag::updateAction(Qt::DropAction action) +{ + Q_D(QPlatformDrag); + if (d->cursor_drop_action != action) { + d->cursor_drop_action = action; + emit currentDrag()->actionChanged(action); + } +} + +static const char *const default_pm[] = { +"13 9 3 1", +". c None", +" c #000000", +"X c #FFFFFF", +"X X X X X X X", +" X X X X X X ", +"X ......... X", +" X.........X ", +"X ......... X", +" X.........X ", +"X ......... X", +" X X X X X X ", +"X X X X X X X", +}; + +Q_GLOBAL_STATIC_WITH_ARGS(QPixmap,qt_drag_default_pixmap,(default_pm)) + +QPixmap QPlatformDrag::defaultPixmap() +{ + return *qt_drag_default_pixmap(); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformdrag_qpa.h b/src/gui/kernel/qplatformdrag_qpa.h index 0c215071d3..7d22c69947 100644 --- a/src/gui/kernel/qplatformdrag_qpa.h +++ b/src/gui/kernel/qplatformdrag_qpa.h @@ -43,6 +43,7 @@ #define QPLATFORMDRAG_H #include +#include QT_BEGIN_HEADER @@ -51,18 +52,54 @@ QT_BEGIN_NAMESPACE class QMimeData; class QMouseEvent; +class QDrag; +class QObject; +class QEvent; +class QPlatformDragPrivate; -class QPlatformDrag +class Q_GUI_EXPORT QPlatformDropQtResponse { public: - virtual ~QPlatformDrag() {} + QPlatformDropQtResponse(bool accepted, Qt::DropAction acceptedAction); + bool isAccepted() const; + Qt::DropAction acceptedAction() const; +private: + bool m_accepted; + Qt::DropAction m_accepted_action; + +}; + +class Q_GUI_EXPORT QPlatformDragQtResponse : public QPlatformDropQtResponse +{ +public: + QPlatformDragQtResponse(bool accepted, Qt::DropAction acceptedAction, QRect answerRect); + + QRect answerRect() const; + +private: + QRect m_answer_rect; +}; + +class Q_GUI_EXPORT QPlatformDrag +{ + Q_DECLARE_PRIVATE(QPlatformDrag) +public: + QPlatformDrag(); + virtual ~QPlatformDrag(); + + QDrag *currentDrag() const; virtual QMimeData *platformDropData() = 0; - virtual void startDrag() {} - virtual void move(const QMouseEvent *me) = 0; - virtual void drop(const QMouseEvent *me) = 0; - virtual void cancel() = 0; + virtual Qt::DropAction drag(QDrag *m_drag) = 0; + void updateAction(Qt::DropAction action); + + Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const; + + static QPixmap defaultPixmap(); + +private: + QPlatformDragPrivate *d_ptr; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 40a4ec07a6..5b77d97950 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -43,6 +43,7 @@ #include "private/qguiapplication_p.h" #include "private/qtouchdevice_p.h" #include +#include #include QT_BEGIN_NAMESPACE @@ -447,14 +448,14 @@ int QWindowSystemInterface::windowSystemEventsQueued() return QWindowSystemInterfacePrivate::windowSystemEventsQueued(); } -Qt::DropAction QWindowSystemInterface::handleDrag(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDragQtResponse QWindowSystemInterface::handleDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - return QGuiApplicationPrivate::processDrag(w, dropData, p); + return QGuiApplicationPrivate::processDrag(w, dropData, p,supportedActions); } -Qt::DropAction QWindowSystemInterface::handleDrop(QWindow *w, QMimeData *dropData, const QPoint &p) +QPlatformDropQtResponse QWindowSystemInterface::handleDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) { - return QGuiApplicationPrivate::processDrop(w, dropData, p); + return QGuiApplicationPrivate::processDrop(w, dropData, p,supportedActions); } /*! diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h index 836fb40bd7..6dae11ea81 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE class QMimeData; class QTouchDevice; +class QPlatformDragQtResponse; +class QPlatformDropQtResponse; class Q_GUI_EXPORT QWindowSystemInterface @@ -122,8 +124,8 @@ public: static void handleSynchronousExposeEvent(QWindow *tlw, const QRegion ®ion); // Drag and drop. These events are sent immediately. - static Qt::DropAction handleDrag(QWindow *w, QMimeData *dropData, const QPoint &p); - static Qt::DropAction handleDrop(QWindow *w, QMimeData *dropData, const QPoint &p); + static QPlatformDragQtResponse handleDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); + static QPlatformDropQtResponse handleDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions); static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result); diff --git a/src/platformsupport/dnd/dnd.pri b/src/platformsupport/dnd/dnd.pri index e100dd10cb..47feb81ef2 100644 --- a/src/platformsupport/dnd/dnd.pri +++ b/src/platformsupport/dnd/dnd.pri @@ -1,4 +1,6 @@ HEADERS += \ - $$PWD/qsimpledrag_p.h + $$PWD/qsimpledrag_p.h \ + $$PWD/qshapedpixmapdndwindow_p.h SOURCES += \ - $$PWD/qsimpledrag.cpp + $$PWD/qsimpledrag.cpp \ + $$PWD/qshapedpixmapdndwindow.cpp diff --git a/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp b/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp new file mode 100644 index 0000000000..4eed1e7d85 --- /dev/null +++ b/src/platformsupport/dnd/qshapedpixmapdndwindow.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qshapedpixmapdndwindow_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QShapedPixmapWindow::QShapedPixmapWindow() + : QWindow(), + m_backingStore(0) +{ + setSurfaceType(RasterSurface); + setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | + Qt::X11BypassWindowManagerHint | Qt::WindowTransparentForInput); + create(); + m_backingStore = new QBackingStore(this); +} + +void QShapedPixmapWindow::render() +{ + QRect rect(QPoint(), geometry().size()); + + m_backingStore->beginPaint(rect); + + QPaintDevice *device = m_backingStore->paintDevice(); + + { + QPainter p(device); + p.drawPixmap(0, 0, m_pixmap); + } + + m_backingStore->endPaint(); + m_backingStore->flush(rect); +} + +void QShapedPixmapWindow::setPixmap(const QPixmap &pixmap) +{ + m_pixmap = pixmap; +} + +void QShapedPixmapWindow::setHotspot(const QPoint &hotspot) +{ + m_hotSpot = hotspot; +} + +void QShapedPixmapWindow::updateGeometry() +{ + QRect rect(QCursor::pos() - m_hotSpot, m_pixmap.size()); + if (m_backingStore->size() != m_pixmap.size()) + m_backingStore->resize(m_pixmap.size()); + setGeometry(rect); +} + +void QShapedPixmapWindow::exposeEvent(QExposeEvent *) +{ + render(); +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h b/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h new file mode 100644 index 0000000000..36ca6040dd --- /dev/null +++ b/src/platformsupport/dnd/qshapedpixmapdndwindow_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSHAPEDPIXMAPDNDWINDOW_H +#define QSHAPEDPIXMAPDNDWINDOW_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QT_BEGIN_HEADER + +class QShapedPixmapWindow : public QWindow +{ +public: + QShapedPixmapWindow(); + + void render(); + + void setPixmap(const QPixmap &pixmap); + void setHotspot(const QPoint &hotspot); + + void updateGeometry(); + +protected: + void exposeEvent(QExposeEvent *); + +private: + QBackingStore *m_backingStore; + QPixmap m_pixmap; + QPoint m_hotSpot; +}; + +QT_END_HEADER + +QT_END_NAMESPACE + +#endif // QSHAPEDPIXMAPDNDWINDOW_H diff --git a/src/platformsupport/dnd/qsimpledrag.cpp b/src/platformsupport/dnd/qsimpledrag.cpp index d0d08c2445..d3cecd4e44 100644 --- a/src/platformsupport/dnd/qsimpledrag.cpp +++ b/src/platformsupport/dnd/qsimpledrag.cpp @@ -56,147 +56,283 @@ #include "qimagereader.h" #include "qimagewriter.h" +#include +#include + #include #include +#include + QT_BEGIN_NAMESPACE -class QDropData : public QInternalMimeData -{ -public: - QDropData(); - ~QDropData(); +/*! + \class QBasicDrag + \brief QBasicDrag is a base class for implementing platform drag and drop. + \since 5.0 + \internal + \ingroup qpa -protected: - bool hasFormat_sys(const QString &mimeType) const; - QStringList formats_sys() const; - QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const; -}; + QBasicDrag implements QPlatformDrag::drag() by running a local event loop in which + it tracks mouse movements and moves the drag icon (QShapedPixmapWindow) accordingly. + It provides new virtuals allowing for querying whether the receiving window + (within the Qt application or outside) accepts the drag and sets the state accordingly. +*/ -QSimpleDrag::QSimpleDrag() +QBasicDrag::QBasicDrag() : + m_restoreCursor(false), m_eventLoop(0), + m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), + m_drag(0), m_drag_icon_window(0), m_cursor_drop_action(Qt::IgnoreAction) { - m_dropData = new QDropData(); - currentWindow = 0; } -QSimpleDrag::~QSimpleDrag() +QBasicDrag::~QBasicDrag() { - delete m_dropData; + delete m_drag_icon_window; } -QMimeData *QSimpleDrag::platformDropData() +void QBasicDrag::enableEventFilter() { - return m_dropData; + qApp->installEventFilter(this); } -void QSimpleDrag::cancel() +void QBasicDrag::disableEventFilter() { - QDragManager *m = QDragManager::self(); -// qDebug("QDragManager::cancel"); - if (m->object->target()) { - QDragLeaveEvent dle; - QCoreApplication::sendEvent(m->object->target(), &dle); - } - + qApp->removeEventFilter(this); } -void QSimpleDrag::move(const QMouseEvent *me) +bool QBasicDrag::eventFilter(QObject *o, QEvent *e) { - QWindow *window = QGuiApplication::topLevelAt(me->globalPos()); - QPoint pos; - if (window) - pos = me->globalPos() - window->geometry().topLeft(); + if (!m_drag) { + if (e->type() == QEvent::KeyRelease && static_cast(e)->key() == Qt::Key_Escape) { + disableEventFilter(); + exitDndEventLoop(); + return true; // block the key release + } + return false; + } - QDragManager *m = QDragManager::self(); + if (!qobject_cast(o)) + return false; - if (me->buttons()) { - Qt::DropAction prevAction = m->global_accepted_action; + switch (e->type()) { + case QEvent::ShortcutOverride: + // prevent accelerators from firing while dragging + e->accept(); + return true; + + case QEvent::KeyPress: + case QEvent::KeyRelease: + { + QKeyEvent *ke = static_cast(e); + if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) { + cancel(); + resetDndState(true); + disableEventFilter(); + exitDndEventLoop(); - if (currentWindow != window) { - if (currentWindow) { - QDragLeaveEvent dle; - QCoreApplication::sendEvent(currentWindow, &dle); - m->willDrop = false; - m->global_accepted_action = Qt::IgnoreAction; - } - currentWindow = window; - if (currentWindow) { - QDragEnterEvent dee(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers()); - QCoreApplication::sendEvent(currentWindow, &dee); - m->willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction; - m->global_accepted_action = m->willDrop ? dee.dropAction() : Qt::IgnoreAction; - } - m->updateCursor(); - } else if (window) { - Q_ASSERT(currentWindow); - QDragMoveEvent dme(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers()); - if (m->global_accepted_action != Qt::IgnoreAction) { - dme.setDropAction(m->global_accepted_action); - dme.accept(); } - QCoreApplication::sendEvent(currentWindow, &dme); - m->willDrop = dme.isAccepted(); - m->global_accepted_action = m->willDrop ? dme.dropAction() : Qt::IgnoreAction; - m->updatePixmap(); - m->updateCursor(); + return true; // Eat all key events } - if (m->global_accepted_action != prevAction) - m->emitActionChanged(m->global_accepted_action); + + case QEvent::MouseMove: + move(static_cast(e)); + return true; // Eat all mouse events + + case QEvent::MouseButtonRelease: + disableEventFilter(); + + if (canDrop()) { + drop(static_cast(e)); + resetDndState(false); + } else { + cancel(); + resetDndState(true); + } + exitDndEventLoop(); + return true; // Eat all mouse events + + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + case QEvent::Wheel: + return true; + default: + break; } + return false; } -void QSimpleDrag::drop(const QMouseEvent *me) +Qt::DropAction QBasicDrag::drag(QDrag *o) { - QDragManager *m = QDragManager::self(); + m_drag = o; + m_executed_drop_action = Qt::IgnoreAction; + m_can_drop = false; + m_restoreCursor = true; +#ifndef QT_NO_CURSOR + qApp->setOverrideCursor(Qt::DragCopyCursor); + updateCursor(m_executed_drop_action); +#endif + startDrag(); + m_eventLoop = new QEventLoop; + m_eventLoop->exec(); + delete m_eventLoop; + m_eventLoop = 0; + m_drag = 0; + endDrag(); + return m_executed_drop_action; +} - QWindow *window = QGuiApplication::topLevelAt(me->globalPos()); +void QBasicDrag::resetDndState(bool /* deleteSource */) +{ + if (m_restoreCursor) { +#ifndef QT_NO_CURSOR + QGuiApplication::restoreOverrideCursor(); +#endif + m_restoreCursor = false; + } +} + +void QBasicDrag::startDrag() +{ + if (!m_drag_icon_window) + m_drag_icon_window = new QShapedPixmapWindow(); + + m_drag_icon_window->setPixmap(m_drag->pixmap()); + m_drag_icon_window->setHotspot(m_drag->hotSpot()); + m_drag_icon_window->updateGeometry(); + m_drag_icon_window->setVisible(true); + + enableEventFilter(); +} + +void QBasicDrag::endDrag() +{ +} + +void QBasicDrag::cancel() +{ + disableEventFilter(); + m_drag_icon_window->setVisible(false); +} + +void QBasicDrag::move(const QMouseEvent *) +{ + if (m_drag) + m_drag_icon_window->updateGeometry(); +} - if (window) { - QPoint pos = me->globalPos() - window->geometry().topLeft(); +void QBasicDrag::drop(const QMouseEvent *) +{ + disableEventFilter(); + m_drag_icon_window->setVisible(false); +} + +void QBasicDrag::exitDndEventLoop() +{ + if (m_eventLoop && m_eventLoop->isRunning()) + m_eventLoop->exit(); +} - QDropEvent de(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers()); - QCoreApplication::sendEvent(window, &de); - if (de.isAccepted()) - m->global_accepted_action = de.dropAction(); - else - m->global_accepted_action = Qt::IgnoreAction; +void QBasicDrag::updateCursor(Qt::DropAction action) +{ + Qt::CursorShape cursorShape = Qt::ForbiddenCursor; + if (canDrop()) { + switch (action) { + case Qt::CopyAction: + cursorShape = Qt::DragCopyCursor; + break; + case Qt::LinkAction: + cursorShape = Qt::DragLinkCursor; + break; + default: + cursorShape = Qt::DragMoveCursor; + break; + } } - currentWindow = 0; + + QCursor *cursor = qApp->overrideCursor(); + if (cursor && cursorShape != cursor->shape()) { + qApp->changeOverrideCursor(QCursor(cursorShape)); + } + updateAction(action); } +/*! + \class QSimpleDrag + \brief QSimpleDrag implements QBasicDrag for Drag and Drop operations within the Qt Application itself. + \since 5.0 + \internal + \ingroup qpa + The class checks whether the receiving window is a window of the Qt application + and sets the state accordingly. It does not take windows of other applications + into account. +*/ -QDropData::QDropData() - : QInternalMimeData() +QSimpleDrag::QSimpleDrag() : m_current_window(0) { } -QDropData::~QDropData() +QMimeData *QSimpleDrag::platformDropData() { + if (drag()) + return drag()->mimeData(); + return 0; } -QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const +void QSimpleDrag::startDrag() { - QDrag *object = QDragManager::self()->object; - if (!object) - return QVariant(); - QByteArray data = object->mimeData()->data(mimetype); - if (type == QVariant::String) - return QString::fromUtf8(data); - return data; + QBasicDrag::startDrag(); + m_current_window = QGuiApplication::topLevelAt(QCursor::pos()); + if (m_current_window) { + QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_current_window, drag()->mimeData(), QCursor::pos(), drag()->supportedActions()); + setCanDrop(response.isAccepted()); + updateCursor(response.acceptedAction()); + } else { + setCanDrop(false); + updateCursor(Qt::IgnoreAction); + } + setExecutedDropAction(Qt::IgnoreAction); } -bool QDropData::hasFormat_sys(const QString &format) const +void QSimpleDrag::cancel() { - return formats().contains(format); + QBasicDrag::cancel(); + if (drag()) + QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction); + m_current_window = 0; } -QStringList QDropData::formats_sys() const +void QSimpleDrag::move(const QMouseEvent *me) { - QDrag *object = QDragManager::self()->object; - if (object) - return object->mimeData()->formats(); - return QStringList(); + QBasicDrag::move(me); + QWindow *window = QGuiApplication::topLevelAt(me->globalPos()); + if (!window) + return; + + const QPoint pos = me->globalPos() - window->geometry().topLeft(); + const QPlatformDragQtResponse qt_response = + QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions()); + + updateCursor(qt_response.acceptedAction()); + setCanDrop(qt_response.isAccepted()); +} + +void QSimpleDrag::drop(const QMouseEvent *me) +{ + QBasicDrag::drop(me); + QWindow *window = QGuiApplication::topLevelAt(me->globalPos()); + if (!window) + return; + + const QPoint pos = me->globalPos() - window->geometry().topLeft(); + const QPlatformDropQtResponse response = + QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions()); + if (response.isAccepted()) { + setExecutedDropAction(response.acceptedAction()); + } else { + setExecutedDropAction(Qt::IgnoreAction); + } } QT_END_NAMESPACE diff --git a/src/platformsupport/dnd/qsimpledrag_p.h b/src/platformsupport/dnd/qsimpledrag_p.h index 536ae241ff..7270684082 100644 --- a/src/platformsupport/dnd/qsimpledrag_p.h +++ b/src/platformsupport/dnd/qsimpledrag_p.h @@ -44,32 +44,80 @@ #include +#include + QT_BEGIN_NAMESPACE +QT_BEGIN_HEADER + class QMouseEvent; class QWindow; - +class QEventLoop; class QDropData; +class QShapedPixmapWindow; -class QSimpleDrag : public QPlatformDrag +class QBasicDrag : public QPlatformDrag, public QObject { public: - QSimpleDrag(); - ~QSimpleDrag(); + virtual ~QBasicDrag(); - virtual QMimeData *platformDropData(); + virtual Qt::DropAction drag(QDrag *drag); + + virtual bool eventFilter(QObject *o, QEvent *e); -// virtual Qt::DropAction drag(QDrag *); +protected: + QBasicDrag(); + virtual void startDrag(); virtual void cancel(); virtual void move(const QMouseEvent *me); virtual void drop(const QMouseEvent *me); + virtual void endDrag(); + + QShapedPixmapWindow *shapedPixmapWindow() const { return m_drag_icon_window; } + void updateCursor(Qt::DropAction action); + + bool canDrop() const { return m_can_drop; } + void setCanDrop(bool c) { m_can_drop = c; } + + Qt::DropAction executedDropAction() const { return m_executed_drop_action; } + void setExecutedDropAction(Qt::DropAction da) { m_executed_drop_action = da; } + + QDrag *drag() const { return m_drag; } + private: - QDropData *m_dropData; + void enableEventFilter(); + void disableEventFilter(); + void resetDndState(bool deleteSource); + void exitDndEventLoop(); + + bool m_restoreCursor; + QEventLoop *m_eventLoop; + Qt::DropAction m_executed_drop_action; + bool m_can_drop; + QDrag *m_drag; + QShapedPixmapWindow *m_drag_icon_window; + Qt::DropAction m_cursor_drop_action; +}; + +class QSimpleDrag : public QBasicDrag +{ +public: + QSimpleDrag(); + virtual QMimeData *platformDropData(); - QWindow *currentWindow; +protected: + virtual void startDrag(); + virtual void cancel(); + virtual void move(const QMouseEvent *me); + virtual void drop(const QMouseEvent *me); + +private: + QWindow *m_current_window; }; +QT_END_HEADER + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 9f2a1dc00c..89ca6204a8 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -53,8 +53,11 @@ #include #include #include +#include +#include #include +#include #include #include @@ -300,14 +303,13 @@ private: QWindowsDrag *m_drag; Qt::MouseButtons m_currentButtons; - Qt::DropAction m_currentAction; ActionCursorMap m_cursors; ULONG m_refs; }; QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) : - m_drag(drag), m_currentButtons(Qt::NoButton), m_currentAction(Qt::IgnoreAction), + m_drag(drag), m_currentButtons(Qt::NoButton), m_refs(1) { if (QWindowsContext::verboseOLE) @@ -321,24 +323,26 @@ QWindowsOleDropSource::~QWindowsOleDropSource() qDebug("%s", __FUNCTION__); } +/*! + \brief Blend custom pixmap with cursors. +*/ + void QWindowsOleDropSource::createCursors() { - QDragManager *manager = QDragManager::self(); - if (!manager || !manager->object) - return; - const QPixmap pixmap = manager->object->pixmap(); + const QDrag *drag = m_drag->currentDrag(); + const QPixmap pixmap = drag->pixmap(); const bool hasPixmap = !pixmap.isNull(); - if (!hasPixmap && manager->dragPrivate()->customCursors.isEmpty()) + if (!hasPixmap) return; QList actions; actions << Qt::MoveAction << Qt::CopyAction << Qt::LinkAction; if (hasPixmap) actions << Qt::IgnoreAction; - const QPoint hotSpot = manager->object->hotSpot(); + const QPoint hotSpot = drag->hotSpot(); for (int cnum = 0; cnum < actions.size(); ++cnum) { const Qt::DropAction action = actions.at(cnum); - QPixmap cpm = manager->dragCursor(action); + QPixmap cpm = drag->dragCursor(action); if (cpm.isNull()) cpm = m_drag->defaultCursor(action); if (cpm.isNull()) { @@ -361,7 +365,7 @@ void QWindowsOleDropSource::createCursors() const QPoint newHotSpot = hotSpot; QPixmap newCursor(w, h); if (hasPixmap) { - newCursor.fill(QColor(0, 0, 0, 0)); + newCursor.fill(Qt::transparent); QPainter p(&newCursor); const QRect srcRect = pixmap.rect(); const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y())); @@ -375,7 +379,7 @@ void QWindowsOleDropSource::createCursors() const int hotY = hasPixmap ? qMax(0,newHotSpot.y()) : 0; if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY)) - m_cursors.insert(action, sysCursor); + m_cursors.insert(actions.at(cnum), sysCursor); } if (QWindowsContext::verboseOLE) qDebug("%s %d cursors", __FUNCTION__, m_cursors.size()); @@ -432,7 +436,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) { HRESULT hr = S_OK; do { - if (fEscapePressed || QWindowsDrag::instance()->dragBeingCancelled()) { + if (fEscapePressed) { hr = ResultFromScode(DRAGDROP_S_CANCEL); break; } @@ -461,13 +465,11 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) } while (false); - QDragManager::self()->willDrop = hr == DRAGDROP_S_DROP; - if (QWindowsContext::verboseOLE && (QWindowsContext::verboseOLE > 1 || hr != S_OK)) - qDebug("%s fEscapePressed=%d, grfKeyState=%lu buttons=%d willDrop = %d returns 0x%x", + qDebug("%s fEscapePressed=%d, grfKeyState=%lu buttons=%d returns 0x%x", __FUNCTION__, fEscapePressed,grfKeyState, int(m_currentButtons), - QDragManager::self()->willDrop, int(hr)); + int(hr)); return hr; } @@ -479,16 +481,12 @@ QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) { const Qt::DropAction action = translateToQDragDropAction(dwEffect); + m_drag->updateAction(action); if (QWindowsContext::verboseOLE > 2) qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action); - if (m_currentAction != action) { - m_currentAction = action; - QDragManager::self()->emitActionChanged(m_currentAction); - } - - const ActionCursorMap::const_iterator it = m_cursors.constFind(m_currentAction); + const ActionCursorMap::const_iterator it = m_cursors.constFind(action); if (it != m_cursors.constEnd()) { SetCursor(it.value()); return ResultFromScode(S_OK); @@ -510,7 +508,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) */ QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : - m_refs(1), m_window(w), m_currentWindow(0), m_chosenEffect(0), m_lastKeyState(0) + m_refs(1), m_window(w), m_chosenEffect(0), m_lastKeyState(0) { if (QWindowsContext::verboseOLE) qDebug() << __FUNCTION__ << this << w; @@ -558,6 +556,38 @@ QWindow *QWindowsOleDropTarget::findDragOverWindow(const POINTL &pt) const return m_window; } +void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, + const QPoint &point, LPDWORD pdwEffect) +{ + Q_ASSERT(window); + m_lastPoint = point; + m_lastKeyState = grfKeyState; + + QWindowsDrag *windowsDrag = QWindowsDrag::instance(); + const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect); + QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState); + QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState); + + const QPlatformDragQtResponse response = + QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions); + + m_answerRect = response.answerRect(); + const Qt::DropAction action = response.acceptedAction(); + if (response.isAccepted()) { + m_chosenEffect = translateToWinDragEffects(action); + } else { + m_chosenEffect = DROPEFFECT_NONE; + } + *pdwEffect = m_chosenEffect; + if (QWindowsContext::verboseOLE) + qDebug() << __FUNCTION__ << m_window + << windowsDrag->dropData() << " supported actions=" << actions + << " mods=" << QGuiApplicationPrivate::modifier_buttons + << " mouse=" << QGuiApplicationPrivate::mouse_buttons + << " accepted: " << response.isAccepted() << action + << m_answerRect << " effect" << *pdwEffect; +} + QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) @@ -567,124 +597,28 @@ QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, QWindowsDrag::instance()->setDropDataObject(pDataObj); pDataObj->AddRef(); - m_currentWindow = m_window; - sendDragEnterEvent(m_window, grfKeyState, pt, pdwEffect); - *pdwEffect = m_chosenEffect; + const QPoint point = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y)); + handleDrag(m_window, grfKeyState, point, pdwEffect); return NOERROR; } -void QWindowsOleDropTarget::sendDragEnterEvent(QWindow *dragEnterWidget, - DWORD grfKeyState, - POINTL pt, LPDWORD pdwEffect) -{ - Q_ASSERT(dragEnterWidget); - - m_lastPoint = QWindowsGeometryHint::mapFromGlobal(dragEnterWidget, QPoint(pt.x,pt.y)); - m_lastKeyState = grfKeyState; - - m_chosenEffect = DROPEFFECT_NONE; - - QDragManager *manager = QDragManager::self(); - QMimeData *md = manager->dropData(); - const Qt::MouseButtons mouseButtons - = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState); - const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect); - const Qt::KeyboardModifiers keyMods = toQtKeyboardModifiers(grfKeyState); - QDragEnterEvent enterEvent(m_lastPoint, actions, md, mouseButtons, keyMods); - QGuiApplication::sendEvent(m_currentWindow, &enterEvent); - m_answerRect = enterEvent.answerRect(); - if (QWindowsContext::verboseOLE) - qDebug() << __FUNCTION__ << " sent drag enter to " << m_window - << *md << " actions=" << actions - << " mods=" << keyMods << " accepted: " - << enterEvent.isAccepted(); - - if (enterEvent.isAccepted()) - m_chosenEffect = translateToWinDragEffects(enterEvent.dropAction()); - // Documentation states that a drag move event is sent immediately after - // a drag enter event. This will honor widgets overriding dragMoveEvent only: - if (enterEvent.isAccepted()) { - QDragMoveEvent moveEvent(m_lastPoint, actions, md, mouseButtons, keyMods); - m_answerRect = enterEvent.answerRect(); - moveEvent.setDropAction(enterEvent.dropAction()); - moveEvent.accept(); // accept by default, since enter event was accepted. - - QGuiApplication::sendEvent(dragEnterWidget, &moveEvent); - if (moveEvent.isAccepted()) { - m_answerRect = moveEvent.answerRect(); - m_chosenEffect = translateToWinDragEffects(moveEvent.dropAction()); - } else { - m_chosenEffect = DROPEFFECT_NONE; - } - } -} - QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { QWindow *dragOverWindow = findDragOverWindow(pt); - + if (QWindowsContext::verboseOLE) + qDebug("%s widget=%p key=%lu, pt=%ld,%ld", __FUNCTION__, dragOverWindow, grfKeyState, pt.x, pt.y); const QPoint tmpPoint = QWindowsGeometryHint::mapFromGlobal(dragOverWindow, QPoint(pt.x,pt.y)); // see if we should compress this event if ((tmpPoint == m_lastPoint || m_answerRect.contains(tmpPoint)) && m_lastKeyState == grfKeyState) { *pdwEffect = m_chosenEffect; + if (QWindowsContext::verboseOLE) + qDebug("%s: compressed event", __FUNCTION__); return NOERROR; } - if (QWindowsContext::verboseOLE > 1) - qDebug().nospace() << '>' << __FUNCTION__ << ' ' << m_window << " current " - << dragOverWindow << " key=" << grfKeyState - << " pt=" < dragOverWindowGuard(dragOverWindow); - // Send drag leave event to the previous drag widget. - // Drag-Over widget might be deleted in DragLeave, - // (tasktracker 218353). - QDragLeaveEvent dragLeave; - if (m_currentWindow) - QGuiApplication::sendEvent(m_currentWindow, &dragLeave); - if (!dragOverWindowGuard) { - dragOverWindow = findDragOverWindow(pt); - } - // Send drag enter event to the current drag widget. - m_currentWindow = dragOverWindow; - sendDragEnterEvent(dragOverWindow, grfKeyState, pt, pdwEffect); - } - - QDragManager *manager = QDragManager::self(); - QMimeData *md = manager->dropData(); - - const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect); - - QDragMoveEvent oldEvent(m_lastPoint, actions, md, - QWindowsMouseHandler::keyStateToMouseButtons(m_lastKeyState), - toQtKeyboardModifiers(m_lastKeyState)); - - m_lastPoint = tmpPoint; - m_lastKeyState = grfKeyState; - - QDragMoveEvent e(tmpPoint, actions, md, - QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState), - toQtKeyboardModifiers(grfKeyState)); - if (m_chosenEffect != DROPEFFECT_NONE) { - if (oldEvent.dropAction() == e.dropAction() && - oldEvent.keyboardModifiers() == e.keyboardModifiers()) - e.setDropAction(translateToQDragDropAction(m_chosenEffect)); - e.accept(); - } - QGuiApplication::sendEvent(dragOverWindow, &e); - - m_answerRect = e.answerRect(); - if (e.isAccepted()) - m_chosenEffect = translateToWinDragEffects(e.dropAction()); - else - m_chosenEffect = DROPEFFECT_NONE; - *pdwEffect = m_chosenEffect; - - if (QWindowsContext::verboseOLE > 1) - qDebug("<%s effect=0x%lx", __FUNCTION__, m_chosenEffect); + handleDrag(dragOverWindow, grfKeyState, tmpPoint, pdwEffect); return NOERROR; } @@ -694,9 +628,7 @@ QWindowsOleDropTarget::DragLeave() if (QWindowsContext::verboseOLE) qDebug().nospace() <<__FUNCTION__ << ' ' << m_window; - m_currentWindow = 0; - QDragLeaveEvent e; - QGuiApplication::sendEvent(m_window, &e); + QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction); QWindowsDrag::instance()->releaseDropDataObject(); return NOERROR; @@ -724,21 +656,15 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, m_lastKeyState = grfKeyState; QWindowsDrag *windowsDrag = QWindowsDrag::instance(); - QDragManager *manager = QDragManager::self(); - QMimeData *md = manager->dropData(); - QDropEvent e(m_lastPoint, translateToQDragDropActions(*pdwEffect), md, - QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState), - toQtKeyboardModifiers(grfKeyState)); - if (m_chosenEffect != DROPEFFECT_NONE) - e.setDropAction(translateToQDragDropAction(m_chosenEffect)); - - QGuiApplication::sendEvent(dropWindow, &e); - if (m_chosenEffect != DROPEFFECT_NONE) - e.accept(); - - if (e.isAccepted()) { - if (e.dropAction() == Qt::MoveAction || e.dropAction() == Qt::TargetMoveAction) { - if (e.dropAction() == Qt::MoveAction) + + const QPlatformDropQtResponse response = + QWindowSystemInterface::handleDrop(dropWindow, windowsDrag->platformDropData(), m_lastPoint, + translateToQDragDropActions(*pdwEffect)); + + if (response.isAccepted()) { + const Qt::DropAction action = response.acceptedAction(); + if (action == Qt::MoveAction || action == Qt::TargetMoveAction) { + if (action == Qt::MoveAction) m_chosenEffect = DROPEFFECT_MOVE; else m_chosenEffect = DROPEFFECT_COPY; @@ -760,7 +686,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, windowsDrag->dropDataObject()->SetData(&format, &medium, true); } } else { - m_chosenEffect = translateToWinDragEffects(e.dropAction()); + m_chosenEffect = translateToWinDragEffects(action); } } else { m_chosenEffect = DROPEFFECT_NONE; @@ -778,7 +704,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, \ingroup qt-lighthouse-win */ -QWindowsDrag::QWindowsDrag() : m_dropDataObject(0), m_dragBeingCancelled(false) +QWindowsDrag::QWindowsDrag() : m_dropDataObject(0) { } @@ -786,6 +712,17 @@ QWindowsDrag::~QWindowsDrag() { } +/*! + \brief Return data for a drop in process. If it stems from a current drag, use a shortcut. +*/ + +QMimeData *QWindowsDrag::dropData() +{ + if (const QDrag *drag = currentDrag()) + return drag->mimeData(); + return &m_dropData; +} + QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const { switch (action) { @@ -810,69 +747,46 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const return m_ignoreDragCursor; } -void QWindowsDrag::startDrag() +Qt::DropAction QWindowsDrag::drag(QDrag *drag) { // TODO: Accessibility handling? - QDragManager *dragManager = QDragManager::self(); - QMimeData *dropData = dragManager->dropData(); - m_dragBeingCancelled = false; + QMimeData *dropData = drag->mimeData(); + Qt::DropAction dragResult = Qt::IgnoreAction; DWORD resultEffect; QWindowsOleDropSource *windowDropSource = new QWindowsOleDropSource(this); windowDropSource->createCursors(); QWindowsOleDataObject *dropDataObject = new QWindowsOleDataObject(dropData); - const Qt::DropActions possibleActions = dragManager->possible_actions; + const Qt::DropActions possibleActions = drag->supportedActions(); const DWORD allowedEffects = translateToWinDragEffects(possibleActions); if (QWindowsContext::verboseOLE) qDebug(">%s possible Actions=%x, effects=0x%lx", __FUNCTION__, int(possibleActions), allowedEffects); const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect); const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect(); - Qt::DropAction ret = Qt::IgnoreAction; if (r == DRAGDROP_S_DROP) { if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) { - ret = Qt::TargetMoveAction; + dragResult = Qt::TargetMoveAction; resultEffect = DROPEFFECT_MOVE; } else { - ret = translateToQDragDropAction(resultEffect); + dragResult = translateToQDragDropAction(resultEffect); } // Force it to be a copy if an unsupported operation occurred. // This indicates a bug in the drop target. - if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects)) - ret = Qt::CopyAction; - } else { - dragManager->setCurrentTarget(0); + if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects)) { + qWarning("%s: Forcing Qt::CopyAction", __FUNCTION__); + dragResult = Qt::CopyAction; + } } - // clean up dropDataObject->releaseQt(); dropDataObject->Release(); // Will delete obj if refcount becomes 0 windowDropSource->Release(); // Will delete src if refcount becomes 0 if (QWindowsContext::verboseOLE) qDebug("<%s allowedEffects=0x%lx, reportedPerformedEffect=0x%lx, resultEffect=0x%lx, hr=0x%x, dropAction=%d", - __FUNCTION__, allowedEffects, reportedPerformedEffect, resultEffect, int(r), ret); -} - -void QWindowsDrag::move(const QMouseEvent *me) -{ - const QPoint pos = me->pos(); - if (QWindowsContext::verboseOLE) - qDebug("%s %d %d", __FUNCTION__, pos.x(), pos.y()); -} - -void QWindowsDrag::drop(const QMouseEvent *me) -{ - const QPoint pos = me->pos(); - if (QWindowsContext::verboseOLE) - qDebug("%s %d %d", __FUNCTION__, pos.x(), pos.y()); -} - -void QWindowsDrag::cancel() -{ - // TODO: Accessibility handling? - if (QWindowsContext::verboseOLE) - qDebug("%s", __FUNCTION__); - m_dragBeingCancelled = true; + __FUNCTION__, allowedEffects, reportedPerformedEffect, + resultEffect, int(r), dragResult); + return dragResult; } QWindowsDrag *QWindowsDrag::instance() diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 86b5539f92..7b629baccc 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -45,9 +45,9 @@ #include "qwindowsinternalmimedata.h" #include +#include QT_BEGIN_NAMESPACE - class QWindowsDropMimeData : public QWindowsInternalMimeData { public: QWindowsDropMimeData() {} @@ -73,11 +73,10 @@ public: private: inline QWindow *findDragOverWindow(const POINTL &pt) const; - void sendDragEnterEvent(QWindow *to, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect); + void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect); ULONG m_refs; QWindow *const m_window; - QWindow *m_currentWindow; QRect m_answerRect; QPoint m_lastPoint; DWORD m_chosenEffect; @@ -92,25 +91,20 @@ public: virtual QMimeData *platformDropData() { return &m_dropData; } - virtual void startDrag(); - virtual void move(const QMouseEvent *me); - virtual void drop(const QMouseEvent *me); - virtual void cancel(); + virtual Qt::DropAction drag(QDrag *drag); static QWindowsDrag *instance(); IDataObject *dropDataObject() const { return m_dropDataObject; } void setDropDataObject(IDataObject *dataObject) { m_dropDataObject = dataObject; } void releaseDropDataObject(); - - bool dragBeingCancelled() const { return m_dragBeingCancelled; } + QMimeData *dropData(); QPixmap defaultCursor(Qt::DropAction action) const; private: QWindowsDropMimeData m_dropData; IDataObject *m_dropDataObject; - bool m_dragBeingCancelled; mutable QPixmap m_copyDragCursor; mutable QPixmap m_moveDragCursor; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index fdc2c76fea..04c43eb97f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -714,9 +714,9 @@ void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t * return; if (event->type == atom(QXcbAtom::XdndStatus)) { - drag()->handleStatus(event, false); + drag()->handleStatus(event); } else if (event->type == atom(QXcbAtom::XdndFinished)) { - drag()->handleFinished(event, false); + drag()->handleFinished(event); } QXcbWindow *window = platformWindowFromId(event->window); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index e928fe2d0a..0e3807cd7b 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -52,6 +52,12 @@ #include #include #include +#include + +#include + +#include +#include QT_BEGIN_NAMESPACE @@ -109,12 +115,11 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w) return proxy; } - -class QDropData : public QXcbMime +class QXcbDropData : public QXcbMime { public: - QDropData(QXcbDrag *d); - ~QDropData(); + QXcbDropData(QXcbDrag *d); + ~QXcbDropData(); protected: bool hasFormat_sys(const QString &mimeType) const; @@ -127,10 +132,9 @@ protected: }; -QXcbDrag::QXcbDrag(QXcbConnection *c) - : QXcbObject(c) +QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c) { - dropData = new QDropData(this); + dropData = new QXcbDropData(this); init(); heartbeat = -1; @@ -147,13 +151,13 @@ void QXcbDrag::init() { currentWindow.clear(); + accepted_drop_action = Qt::IgnoreAction; + xdnd_dragsource = XCB_NONE; - last_target_accepted_action = Qt::IgnoreAction; waiting_for_status = false; current_target = XCB_NONE; current_proxy_target = XCB_NONE; - xdnd_dragging = false; source_time = XCB_CURRENT_TIME; target_time = XCB_CURRENT_TIME; @@ -169,16 +173,17 @@ QMimeData *QXcbDrag::platformDropData() void QXcbDrag::startDrag() { + // #fixme enableEventFilter(); + init(); heartbeat = startTimer(200); - xdnd_dragging = true; + xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(), atom(QXcbAtom::XdndSelection), connection()->time()); - QDragManager *manager = QDragManager::self(); - QStringList fmts = QXcbMime::formatsHelper(manager->dropData()); + QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData()); for (int i = 0; i < fmts.size(); ++i) { QList atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i)); for (int j = 0; j < atoms.size(); ++j) { @@ -190,23 +195,16 @@ void QXcbDrag::startDrag() xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(), atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData()); - - QPointF pos = QCursor::pos(); - QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - move(&me); - -// if (!QWidget::mouseGrabber()) -// manager->shapedPixmapWindow->grabMouse(); + QBasicDrag::startDrag(); } void QXcbDrag::endDrag() { - Q_ASSERT(heartbeat != -1); - killTimer(heartbeat); - heartbeat = -1; - - xdnd_dragging = false; + if (heartbeat != -1) { + killTimer(heartbeat); + heartbeat = -1; + } + QBasicDrag::endDrag(); } static xcb_translate_coordinates_reply_t * @@ -219,7 +217,7 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md) { - if (w == QDragManager::self()->shapedPixmapWindow->handle()->winId()) + if (w == shapedPixmapWindow()->handle()->winId()) return 0; if (md) { @@ -296,9 +294,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md void QXcbDrag::move(const QMouseEvent *me) { - DEBUG() << "QDragManager::move enter" << me->globalPos(); - - // ### + QBasicDrag::move(me); QPoint globalPos = me->globalPos(); if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid()) @@ -337,15 +333,13 @@ void QXcbDrag::move(const QMouseEvent *me) ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y()); if (!translate) return; + xcb_window_t target = translate->child; int lx = translate->dst_x; int ly = translate->dst_y; free (translate); - if (target == rootwin) { - // Ok. - } else if (target) { - //me + if (target && target != rootwin) { xcb_window_t src = rootwin; while (target != 0) { DNDDEBUG << "checking target for XdndAware" << target << lx << ly; @@ -376,7 +370,7 @@ void QXcbDrag::move(const QMouseEvent *me) target = child; } - if (!target || target == QDragManager::self()->shapedPixmapWindow->handle()->winId()) { + if (!target || target == shapedPixmapWindow()->handle()->winId()) { DNDDEBUG << "need to find real window"; target = findRealWindow(globalPos, rootwin, 6); DNDDEBUG << "real window found" << target; @@ -393,9 +387,6 @@ void QXcbDrag::move(const QMouseEvent *me) target = rootwin; } - DNDDEBUG << "and the final target is " << target; - DNDDEBUG << "the widget w is" << (w ? w->window() : 0); - xcb_window_t proxy_target = xdndProxy(connection(), target); if (!proxy_target) proxy_target = target; @@ -414,7 +405,6 @@ void QXcbDrag::move(const QMouseEvent *me) free(reply); } - DEBUG() << "target=" << target << "current_target=" << current_target; if (target != current_target) { if (current_target) send_leave(); @@ -447,11 +437,10 @@ void QXcbDrag::move(const QMouseEvent *me) waiting_for_status = false; } } + if (waiting_for_status) return; - QDragManager *m = QDragManager::self(); - if (target) { waiting_for_status = true; @@ -465,28 +454,21 @@ void QXcbDrag::move(const QMouseEvent *me) move.data.data32[1] = 0; // flags move.data.data32[2] = (globalPos.x() << 16) + globalPos.y(); move.data.data32[3] = connection()->time(); - move.data.data32[4] = toXdndAction(m->defaultAction(m->dragPrivate()->possible_actions, QGuiApplication::keyboardModifiers())); + move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers())); DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window; source_time = connection()->time(); if (w) - handle_xdnd_position(w->window(), &move, false); + handle_xdnd_position(w->window(), &move); else xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move); - } else { - if (m->willDrop) { - m->willDrop = false; - } } - m->updateCursor(); - DEBUG() << "QDragManager::move leave"; } -void QXcbDrag::drop(const QMouseEvent *) +void QXcbDrag::drop(const QMouseEvent *event) { - endDrag(); - + QBasicDrag::drop(event); if (!current_target) return; @@ -500,14 +482,13 @@ void QXcbDrag::drop(const QMouseEvent *) drop.data.data32[2] = connection()->time(); drop.data.data32[3] = 0; - drop.data.data32[4] = 0; + drop.data.data32[4] = currentDrag()->supportedActions(); QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target); if (w && (w->window()->windowType() == Qt::Desktop) /*&& !w->acceptDrops()*/) w = 0; - QDragManager *manager = QDragManager::self(); Transaction t = { connection()->time(), @@ -515,21 +496,22 @@ void QXcbDrag::drop(const QMouseEvent *) current_proxy_target, (w ? w->window() : 0), // current_embedding_widget, - manager->object + currentDrag() }; transactions.append(t); restartDropExpiryTimer(); - if (w) - handleDrop(w->window(), &drop, false); - else + if (w) { + handleDrop(w->window(), &drop); + } else { xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop); + } current_target = 0; current_proxy_target = 0; source_time = 0; // current_embedding_widget = 0; - manager->object = 0; + // #fixme resetDndState(false); } Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const @@ -719,7 +701,7 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev DEBUG() << " " << connection()->atomName(xdnd_types.at(i)); } -void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e, bool passive) +void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e) { QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff); Q_ASSERT(w); @@ -727,11 +709,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t p -= geometry.topLeft(); - // #### -// if (!passive && checkEmbedded(w, e)) -// return; - - if (!w || (/*!w->acceptDrops() &&*/ (w->windowType() == Qt::Desktop))) + if (!w || (w->windowType() == Qt::Desktop)) return; if (e->data.data32[0] != xdnd_dragsource) { @@ -739,12 +717,27 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t return; } + currentPosition = p; + currentWindow = w; + // timestamp from the source - if (e->data.data32[3] != XCB_NONE) - target_time /*= X11->userTime*/ = e->data.data32[3]; + if (e->data.data32[3] != XCB_NONE) { + target_time = e->data.data32[3]; + } - QDragManager *manager = QDragManager::self(); - QMimeData *dropData = manager->dropData(); + QMimeData *dropData = 0; + Qt::DropActions supported_actions = Qt::IgnoreAction; + if (currentDrag()) { + dropData = currentDrag()->mimeData(); + supported_actions = currentDrag()->supportedActions(); + } else { + dropData = platformDropData(); + supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); + } + + QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions); + QRect answerRect(p + geometry.topLeft(), QSize(1,1)); + answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry); xcb_client_message_event_t response; response.response_type = XCB_CLIENT_MESSAGE; @@ -752,83 +745,33 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t response.format = 32; response.type = atom(QXcbAtom::XdndStatus); response.data.data32[0] = xcb_window(w); - response.data.data32[1] = 0; // flags + response.data.data32[1] = qt_response.isAccepted(); // flags response.data.data32[2] = 0; // x, y response.data.data32[3] = 0; // w, h - response.data.data32[4] = 0; // action - - if (!passive) { // otherwise just reject - QRect answerRect(p + geometry.topLeft(), QSize(1,1)); - - if (manager->object) { - manager->possible_actions = manager->dragPrivate()->possible_actions; - } else { - manager->possible_actions = Qt::DropActions(toDropAction(e->data.data32[4])); - } - QDragMoveEvent me(p, manager->possible_actions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - - Qt::DropAction accepted_action = Qt::IgnoreAction; + response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action - currentPosition = p; - if (w != currentWindow.data()) { - if (currentWindow) { - QDragLeaveEvent e; - QGuiApplication::sendEvent(currentWindow.data(), &e); - } - currentWindow = w; - last_target_accepted_action = Qt::IgnoreAction; - QDragEnterEvent de(p, manager->possible_actions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - QGuiApplication::sendEvent(w, &de); - if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction) - last_target_accepted_action = de.dropAction(); - } + if (answerRect.left() < 0) + answerRect.setLeft(0); + if (answerRect.right() > 4096) + answerRect.setRight(4096); + if (answerRect.top() < 0) + answerRect.setTop(0); + if (answerRect.bottom() > 4096) + answerRect.setBottom(4096); + if (answerRect.width() < 0) + answerRect.setWidth(0); + if (answerRect.height() < 0) + answerRect.setHeight(0); - DEBUG() << "qt_handle_xdnd_position action=" << connection()->atomName(e->data.data32[4]); - - if (last_target_accepted_action != Qt::IgnoreAction) { - me.setDropAction(last_target_accepted_action); - me.accept(); - } - QGuiApplication::sendEvent(w, &me); - if (me.isAccepted()) { - response.data.data32[1] = 1; // yes - accepted_action = me.dropAction(); - last_target_accepted_action = accepted_action; - } else { - response.data.data32[0] = 0; - last_target_accepted_action = Qt::IgnoreAction; - } - answerRect = me.answerRect().translated(geometry.topLeft()).intersected(geometry); - - if (answerRect.left() < 0) - answerRect.setLeft(0); - if (answerRect.right() > 4096) - answerRect.setRight(4096); - if (answerRect.top() < 0) - answerRect.setTop(0); - if (answerRect.bottom() > 4096) - answerRect.setBottom(4096); - if (answerRect.width() < 0) - answerRect.setWidth(0); - if (answerRect.height() < 0) - answerRect.setHeight(0); - -// response.data.data32[2] = (answerRect.x() << 16) + answerRect.y(); -// response.data.data32[3] = (answerRect.width() << 16) + answerRect.height(); - response.data.data32[4] = toXdndAction(accepted_action); - } + response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // reset target_time = XCB_CURRENT_TIME; - DEBUG() << "sending XdndStatus" << (xdnd_dragsource == connection()->clipboard()->owner()) << xdnd_dragsource - << response.data.data32[1] << connection()->atomName(response.data.data32[4]); if (xdnd_dragsource == connection()->clipboard()->owner()) - handle_xdnd_status(&response, passive); + handle_xdnd_status(&response); else Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource, XCB_EVENT_MASK_NO_EVENT, (const char *)&response)); @@ -850,7 +793,7 @@ namespace }; } -void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event, bool passive) +void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event) { xcb_client_message_event_t *lastEvent = const_cast(event); xcb_generic_event_t *nextEvent; @@ -861,19 +804,28 @@ void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *eve lastEvent = (xcb_client_message_event_t *)nextEvent; } - handle_xdnd_position(w, lastEvent, passive); + handle_xdnd_position(w, lastEvent); if (lastEvent != event) free(lastEvent); } -void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool) +void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event) { DEBUG("xdndHandleStatus"); + waiting_for_status = false; // ignore late status messages if (event->data.data32[0] && event->data.data32[0] != current_proxy_target) return; - Qt::DropAction newAction = (event->data.data32[1] & 0x1) ? toDropAction(event->data.data32[4]) : Qt::IgnoreAction; + const bool dropPossible = event->data.data32[1]; + setCanDrop(dropPossible); + + if (dropPossible) { + accepted_drop_action = toDropAction(event->data.data32[4]); + updateCursor(accepted_drop_action); + } else { + updateCursor(Qt::IgnoreAction); + } if ((event->data.data32[1] & 2) == 0) { QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff); @@ -882,18 +834,9 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool) } else { source_sameanswer = QRect(); } - QDragManager *manager = QDragManager::self(); - manager->willDrop = (event->data.data32[1] & 0x1); - if (manager->global_accepted_action != newAction) { - manager->global_accepted_action = newAction; - manager->emitActionChanged(newAction); - } - DEBUG() << "willDrop=" << manager->willDrop << "action=" << newAction; - manager->updateCursor(); - waiting_for_status = false; } -void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passive) +void QXcbDrag::handleStatus(const xcb_client_message_event_t *event) { if (event->window != connection()->clipboard()->owner()) return; @@ -907,13 +850,13 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passiv lastEvent = (xcb_client_message_event_t *)nextEvent; } - handle_xdnd_status(lastEvent, passive); + handle_xdnd_status(lastEvent); if (lastEvent != event) free(lastEvent); DEBUG("xdndHandleStatus end"); } -void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/) +void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event) { DEBUG("xdnd leave"); if (!currentWindow || w != currentWindow.data()) @@ -931,8 +874,8 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event, DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource); } - QDragLeaveEvent e; - QGuiApplication::sendEvent(currentWindow.data(), &e); + QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction); + updateAction(Qt::IgnoreAction); xdnd_dragsource = 0; xdnd_types.clear(); @@ -944,7 +887,6 @@ void QXcbDrag::send_leave() if (!current_target) return; - QDragManager *manager = QDragManager::self(); xcb_client_message_event_t leave; leave.response_type = XCB_CLIENT_MESSAGE; @@ -963,24 +905,18 @@ void QXcbDrag::send_leave() w = 0; if (w) - handleLeave(w->window(), (const xcb_client_message_event_t *)&leave, false); + handleLeave(w->window(), (const xcb_client_message_event_t *)&leave); else xcb_send_event(xcb_connection(), false,current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&leave); - // reset the drag manager state - manager->willDrop = false; - if (manager->global_accepted_action != Qt::IgnoreAction) - manager->emitActionChanged(Qt::IgnoreAction); - manager->global_accepted_action = Qt::IgnoreAction; - manager->updateCursor(); current_target = 0; current_proxy_target = 0; source_time = XCB_CURRENT_TIME; waiting_for_status = false; } -void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive) +void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event) { DEBUG("xdndHandleDrop"); if (!currentWindow) { @@ -988,16 +924,8 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo return; // sanity } - // ### -// if (!passive && checkEmbedded(currentWindow, xe)){ -// current_embedding_widget = 0; -// xdnd_dragsource = 0; -// currentWindow = 0; -// return; -// } const uint32_t *l = event->data.data32; - QDragManager *manager = QDragManager::self(); DEBUG("xdnd drop"); if (l[0] != xdnd_dragsource) { @@ -1009,50 +937,39 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo if (l[2] != 0) target_time = /*X11->userTime =*/ l[2]; - if (!passive) { - // this could be a same-application drop, just proxied due to - // some XEMBEDding, so try to find the real QMimeData used - // based on the timestamp for this drop. - QMimeData *dropData = 0; - // ### -// int at = findXdndDropTransactionByTime(target_time); -// if (at != -1) -// dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; - // if we can't find it, then use the data in the drag manager - if (!dropData) - dropData = manager->dropData(); - - // Drop coming from another app? Update keyboard modifiers. -// if (!qt_xdnd_dragging) { -// QApplicationPrivate::modifier_buttons = currentKeyboardModifiers(); -// } - - QDropEvent de(currentPosition, manager->possible_actions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); - QGuiApplication::sendEvent(currentWindow.data(), &de); - if (!de.isAccepted()) { - // Ignore a failed drag - manager->global_accepted_action = Qt::IgnoreAction; - } else { - manager->global_accepted_action = de.dropAction(); - } - xcb_client_message_event_t finished; - finished.response_type = XCB_CLIENT_MESSAGE; - finished.window = xdnd_dragsource; - finished.format = 32; - finished.type = atom(QXcbAtom::XdndFinished); - DNDDEBUG << "xdndHandleDrop" - << "currentWindow" << currentWindow.data() - << (currentWindow ? xcb_window(currentWindow.data()) : 0); - finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE; - finished.data.data32[1] = de.isAccepted() ? 1 : 0; // flags - finished.data.data32[2] = toXdndAction(manager->global_accepted_action); - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource, - XCB_EVENT_MASK_NO_EVENT, (char *)&finished)); + // this could be a same-application drop, just proxied due to + // some XEMBEDding, so try to find the real QMimeData used + // based on the timestamp for this drop. + Qt::DropActions supported_drop_actions(l[4]); + QMimeData *dropData = 0; + if (currentDrag()) { + dropData = currentDrag()->mimeData(); } else { - QDragLeaveEvent e; - QGuiApplication::sendEvent(currentWindow.data(), &e); + dropData = platformDropData(); } + + if (!dropData) + return; + // ### + // int at = findXdndDropTransactionByTime(target_time); + // if (at != -1) + // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data; + // if we can't find it, then use the data in the drag manager + + QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions); + setExecutedDropAction(response.acceptedAction()); + + xcb_client_message_event_t finished; + finished.response_type = XCB_CLIENT_MESSAGE; + finished.window = xdnd_dragsource; + finished.format = 32; + finished.type = atom(QXcbAtom::XdndFinished); + finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE; + finished.data.data32[1] = response.isAccepted(); // flags + finished.data.data32[2] = toXdndAction(response.acceptedAction()); + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource, + XCB_EVENT_MASK_NO_EVENT, (char *)&finished)); + xdnd_dragsource = 0; currentWindow.clear(); waiting_for_status = false; @@ -1062,7 +979,7 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo } -void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool) +void QXcbDrag::handleFinished(const xcb_client_message_event_t *event) { DEBUG("xdndHandleFinished"); if (event->window != connection()->clipboard()->owner()) @@ -1099,8 +1016,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool) // current_target = 0; // current_proxy_target = 0; - if (t.object) - t.object->deleteLater(); + if (t.drag) + t.drag->deleteLater(); // current_target = target; // current_proxy_target = proxy_target; @@ -1126,7 +1043,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e) // dnd within the same process, don't delete these continue; } - t.object->deleteLater(); + t.drag->deleteLater(); transactions.removeAt(i--); } @@ -1138,12 +1055,9 @@ void QXcbDrag::timerEvent(QTimerEvent* e) void QXcbDrag::cancel() { DEBUG("QXcbDrag::cancel"); - endDrag(); - + QBasicDrag::cancel(); if (current_target) send_leave(); - - current_target = 0; } @@ -1157,14 +1071,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event notify.property = XCB_NONE; notify.time = event->time; - QDragManager *manager = QDragManager::self(); - QDrag *currentObject = manager->object; - // which transaction do we use? (note: -2 means use current manager->object) int at = -1; // figure out which data the requestor is really interested in - if (manager->object && event->time == source_time) { + if (currentDrag() && event->time == source_time) { // requestor wants the current drag data at = -2; } else { @@ -1188,20 +1099,18 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event // } // } } + + QDrag *transactionDrag = 0; if (at >= 0) { restartDropExpiryTimer(); - // use the drag object from an XdndDrop tansaction - manager->object = transactions.at(at).object; - } else if (at != -2) { - // no transaction found, we'll have to reject the request - manager->object = 0; + transactionDrag = transactions.at(at).drag; } - if (manager->object) { + if (transactionDrag) { xcb_atom_t atomFormat = event->target; int dataFormat = 0; QByteArray data; - if (QXcbMime::mimeDataForAtom(connection(), event->target, manager->dragPrivate()->data, + if (QXcbMime::mimeDataForAtom(connection(), event->target, transactionDrag->mimeData(), &data, &atomFormat, &dataFormat)) { int dataSize = data.size() / (dataFormat / 8); xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, event->requestor, event->property, @@ -1211,9 +1120,6 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event } } - // reset manager->object in case we modified it above - manager->object = currentObject; - xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)¬ify); } @@ -1268,20 +1174,17 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on) } } - - - -QDropData::QDropData(QXcbDrag *d) +QXcbDropData::QXcbDropData(QXcbDrag *d) : QXcbMime(), drag(d) { } -QDropData::~QDropData() +QXcbDropData::~QXcbDropData() { } -QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const +QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const { QByteArray mime = mimetype.toLatin1(); QVariant data = /*X11->motifdnd_active @@ -1290,17 +1193,16 @@ QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type req return data; } -QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const +QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const { QByteArray result; - QDragManager *manager = QDragManager::self(); QXcbConnection *c = drag->connection(); QXcbWindow *xcb_window = c->platformWindowFromId(drag->xdnd_dragsource); - if (xcb_window && manager->object && xcb_window->window()->windowType() != Qt::Desktop) { - QDragPrivate *o = manager->dragPrivate(); - if (o->data->hasFormat(QLatin1String(format))) - result = o->data->data(QLatin1String(format)); + if (xcb_window && drag->currentDrag() && xcb_window->window()->windowType() != Qt::Desktop) { + QMimeData *data = drag->currentDrag()->mimeData(); + if (data->hasFormat(QLatin1String(format))) + result = data->data(QLatin1String(format)); return result; } @@ -1320,12 +1222,12 @@ QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requ } -bool QDropData::hasFormat_sys(const QString &format) const +bool QXcbDropData::hasFormat_sys(const QString &format) const { return formats().contains(format); } -QStringList QDropData::formats_sys() const +QStringList QXcbDropData::formats_sys() const { QStringList formats; // if (X11->motifdnd_active) { diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index e32e630548..710a07a5a4 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -43,6 +43,7 @@ #define QXCBDRAG_H #include +#include #include #include #include @@ -51,17 +52,23 @@ #include #include +#include +#include + +#include + QT_BEGIN_NAMESPACE class QMouseEvent; class QWindow; class QXcbConnection; class QXcbWindow; -class QDropData; +class QXcbDropData; class QXcbScreen; class QDrag; +class QShapedPixmapWindow; -class QXcbDrag : public QObject, public QXcbObject, public QPlatformDrag +class QXcbDrag : public QXcbObject, public QBasicDrag { public: QXcbDrag(QXcbConnection *c); @@ -69,35 +76,36 @@ public: virtual QMimeData *platformDropData(); -// virtual Qt::DropAction drag(QDrag *); - virtual void startDrag(); - virtual void cancel(); - virtual void move(const QMouseEvent *me); - virtual void drop(const QMouseEvent *me); + void startDrag(); + void cancel(); + void move(const QMouseEvent *me); + void drop(const QMouseEvent *me); void endDrag(); void handleEnter(QWindow *window, const xcb_client_message_event_t *event); - void handlePosition(QWindow *w, const xcb_client_message_event_t *event, bool passive); - void handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/); - void handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive); + void handlePosition(QWindow *w, const xcb_client_message_event_t *event); + void handleLeave(QWindow *w, const xcb_client_message_event_t *event); + void handleDrop(QWindow *, const xcb_client_message_event_t *event); - void handleStatus(const xcb_client_message_event_t *event, bool passive); + void handleStatus(const xcb_client_message_event_t *event); void handleSelectionRequest(const xcb_selection_request_event_t *event); - void handleFinished(const xcb_client_message_event_t *event, bool passive); + void handleFinished(const xcb_client_message_event_t *event); bool dndEnable(QXcbWindow *win, bool on); + void updatePixmap(); + protected: void timerEvent(QTimerEvent* e); private: - friend class QDropData; + friend class QXcbDropData; void init(); - void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event, bool passive); - void handle_xdnd_status(const xcb_client_message_event_t *event, bool); + void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event); + void handle_xdnd_status(const xcb_client_message_event_t *event); void send_leave(); Qt::DropAction toDropAction(xcb_atom_t atom) const; @@ -106,7 +114,8 @@ private: QWeakPointer currentWindow; QPoint currentPosition; - QDropData *dropData; + QXcbDropData *dropData; + Qt::DropAction accepted_drop_action; QWindow *desktop_proxy; @@ -118,7 +127,6 @@ private: xcb_timestamp_t target_time; xcb_timestamp_t source_time; - Qt::DropAction last_target_accepted_action; // rectangle in which the answer will be the same QRect source_sameanswer; @@ -132,7 +140,6 @@ private: QXcbScreen *current_screen; int heartbeat; - bool xdnd_dragging; QVector drag_types; @@ -143,7 +150,7 @@ private: xcb_window_t proxy_target; QWindow *targetWindow; // QWidget *embedding_widget; - QDrag *object; + QDrag *drag; }; QList transactions; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 067cb775c8..6b7e73d02f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1257,11 +1257,11 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even } else if (event->type == atom(QXcbAtom::XdndEnter)) { connection()->drag()->handleEnter(window(), event); } else if (event->type == atom(QXcbAtom::XdndPosition)) { - connection()->drag()->handlePosition(window(), event, false); + connection()->drag()->handlePosition(window(), event); } else if (event->type == atom(QXcbAtom::XdndLeave)) { - connection()->drag()->handleLeave(window(), event, false); + connection()->drag()->handleLeave(window(), event); } else if (event->type == atom(QXcbAtom::XdndDrop)) { - connection()->drag()->handleDrop(window(), event, false); + connection()->drag()->handleDrop(window(), event); } else { qWarning() << "unhandled client message:" << connection()->atomName(event->type); } diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp index a5351301a7..feec3fcbc5 100644 --- a/src/widgets/itemviews/qitemdelegate.cpp +++ b/src/widgets/itemviews/qitemdelegate.cpp @@ -44,6 +44,8 @@ #ifndef QT_NO_ITEMVIEWS #include #include +#include +#include #include #include #include @@ -1224,8 +1226,10 @@ bool QItemDelegate::eventFilter(QObject *object, QEvent *event) #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. - if (QDragManager::self() && QDragManager::self()->object != 0) + QPlatformDrag *platformDrag = QGuiApplicationPrivate::instance()->platformIntegration()->drag(); + if (platformDrag && platformDrag->currentDrag()) { return false; + } #endif emit commitData(editor); diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp index ca4c684e98..d54d78512a 100644 --- a/src/widgets/itemviews/qstyleditemdelegate.cpp +++ b/src/widgets/itemviews/qstyleditemdelegate.cpp @@ -44,6 +44,8 @@ #ifndef QT_NO_ITEMVIEWS #include #include +#include +#include #include #include #include @@ -689,8 +691,10 @@ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event) #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. - if (QDragManager::self() && QDragManager::self()->object != 0) + QPlatformDrag *platformDrag = QGuiApplicationPrivate::instance()->platformIntegration()->drag(); + if (platformDrag && platformDrag->currentDrag()) { return false; + } #endif emit commitData(editor); -- cgit v1.2.3 From 0d68a5aabf4f93236df95da8836ecf62c4e92593 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Tue, 28 Feb 2012 12:37:55 +0100 Subject: Remove Mac qDebug ifdefs. Make qDebug work again with the new logging framework. Change-Id: Ib88a83182429636b274d6284933d5ea00db7279c Reviewed-by: Bradley T. Hughes --- src/corelib/kernel/qcore_mac_p.h | 23 ----------------------- src/plugins/platforms/cocoa/qmacdefines_mac.h | 11 ----------- 2 files changed, 34 deletions(-) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 78cb0eff3b..048d746183 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -57,17 +57,6 @@ # define __IMAGECAPTURE__ #endif -#undef OLD_DEBUG -#ifdef DEBUG -# define OLD_DEBUG DEBUG -# undef DEBUG -#endif -#define DEBUG 0 -#ifdef qDebug -# define old_qDebug qDebug -# undef qDebug -#endif - #if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED) #include #else @@ -82,18 +71,6 @@ #include #endif -#undef DEBUG -#ifdef OLD_DEBUG -# define DEBUG OLD_DEBUG -# undef OLD_DEBUG -#endif - -#ifdef old_qDebug -# undef qDebug -# define qDebug QT_NO_QDEBUG_MACRO -# undef old_qDebug -#endif - #include "qstring.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qmacdefines_mac.h b/src/plugins/platforms/cocoa/qmacdefines_mac.h index a35df47227..d89e313bcb 100644 --- a/src/plugins/platforms/cocoa/qmacdefines_mac.h +++ b/src/plugins/platforms/cocoa/qmacdefines_mac.h @@ -93,11 +93,6 @@ Yes, it is an informative comment ;-) #include -#ifdef qDebug -# define old_qDebug qDebug -# undef qDebug -#endif - #ifdef __LP64__ typedef signed int OSStatus; #else @@ -149,9 +144,3 @@ typedef AERecord AppleEvent; #ifdef check #undef check #endif - -#ifdef old_qDebug -# undef qDebug -# define qDebug QT_NO_QDEBUG_MACRO -# undef old_qDebug -#endif -- cgit v1.2.3 From 8034bc9e833a07c8f4b193849055097f0be7f619 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Mon, 27 Feb 2012 13:03:47 +0100 Subject: Don't use deprecated QWheelEvent::delta() Replace with pixelDelta() and angleDelta(). Change-Id: Ie4b8b6fd39a5f8a28433554000940faef2f2542c Reviewed-by: Olivier Goffart --- src/gui/kernel/qevent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index ee121f2071..e902cbf7e2 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2999,7 +2999,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { break; #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: - dbg.nospace() << "QWheelEvent(" << static_cast(e)->delta() + dbg.nospace() << "QWheelEvent(" + << static_cast(e)->pixelDelta() + << static_cast(e)->angleDelta() << ')'; return dbg.space(); #endif -- cgit v1.2.3 From 693a286600e601fde05049c0819034ed8f7a71d6 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 28 Feb 2012 20:49:19 +0100 Subject: Add a test using lots of similar strings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This attempts to emulate a dictionary usecase of sorts, done in code to avoid bloating the git repository by adding an actual word list. Change-Id: I878bc4af8877ba780ee699932f240c0d9c8ff12c Reviewed-by: João Abecasis --- tests/benchmarks/corelib/tools/qhash/main.cpp | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/benchmarks/corelib/tools/qhash/main.cpp b/tests/benchmarks/corelib/tools/qhash/main.cpp index 18138cbd47..db33200d43 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.cpp +++ b/tests/benchmarks/corelib/tools/qhash/main.cpp @@ -67,6 +67,8 @@ private: ///////////////////// QHash ///////////////////// +#include + void tst_QHash::data() { QTest::addColumn("items"); @@ -99,6 +101,40 @@ void tst_QHash::data() QTest::newRow("uuids-list") << uuids; } + { + // lots of strings with alphabetical characters, vaguely reminiscent of + // a dictionary. + // + // this programatically generates a series like: + // AAAAAA + // AAAAAB + // AAAAAC + // ... + // AAAAAZ + // AAAABZ + // ... + // AAAAZZ + // AAABZZ + QByteArray id("AAAAAAA"); + static QStringList dict; + + if (dict.isEmpty()) { + for (int i = id.length() - 1; i > 0;) { + dict.append(id); + char c = id.at(i); + id[i] = ++c; + + if (c == 'Z') { + // wrap to next digit + i--; + id[i] = 'A'; + } + } + } + + QTest::newRow("dictionary") << dict; + } + } void tst_QHash::qhash_qt4() -- cgit v1.2.3 From 0f3d9b1d84354ed19e2522869b1164f135ed8a51 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 28 Feb 2012 20:49:25 +0100 Subject: Add test data for string forms of numbers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to the UUID benchmark, but won't have any non-numerical characters. Change-Id: I7487c97cab96fd53c180fe12061e7be3ca96e883 Reviewed-by: João Abecasis --- tests/benchmarks/corelib/tools/qhash/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/benchmarks/corelib/tools/qhash/main.cpp b/tests/benchmarks/corelib/tools/qhash/main.cpp index db33200d43..f7c0f66df3 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.cpp +++ b/tests/benchmarks/corelib/tools/qhash/main.cpp @@ -135,6 +135,18 @@ void tst_QHash::data() QTest::newRow("dictionary") << dict; } + { + // string versions of numbers. + static QStringList numbers; + + if (numbers.isEmpty()) { + for (int i = 5000000; i < 5005001; ++i) + numbers.append(QString::number(i)); + } + + QTest::newRow("numbers") << numbers; + } + } void tst_QHash::qhash_qt4() -- cgit v1.2.3 From 57004b7fda861e1e59a00688a859f30d9a088b4e Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 28 Feb 2012 20:49:35 +0100 Subject: Move data generation to initTestCase() method and store the results. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the comments on Ie4100a1ca4dbe7bf1cd73de883a9854377ac2f5e, having Q_ASSERT was not a good idea, and data functions can't really handle QVERIFY/QCOMPARE/etc, so do this in initTestCase instead. Change-Id: I19e61dec7fe415bb1fa0f53a2920d99b8c7c8ea7 Reviewed-by: João Abecasis --- tests/benchmarks/corelib/tools/qhash/main.cpp | 130 ++++++++++++-------------- 1 file changed, 58 insertions(+), 72 deletions(-) diff --git a/tests/benchmarks/corelib/tools/qhash/main.cpp b/tests/benchmarks/corelib/tools/qhash/main.cpp index f7c0f66df3..7a871b455c 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.cpp +++ b/tests/benchmarks/corelib/tools/qhash/main.cpp @@ -54,6 +54,7 @@ class tst_QHash : public QObject Q_OBJECT private slots: + void initTestCase(); void qhash_qt4_data() { data(); } void qhash_qt4(); void qhash_faster_data() { data(); } @@ -63,90 +64,75 @@ private slots: private: void data(); + + QStringList smallFilePaths; + QStringList uuids; + QStringList dict; + QStringList numbers; }; ///////////////////// QHash ///////////////////// #include -void tst_QHash::data() +void tst_QHash::initTestCase() { - QTest::addColumn("items"); - static QStringList smallFilePaths; - - { - // small list of file paths - if (smallFilePaths.isEmpty()) { - QFile smallPathsData("paths_small_data.txt"); - QVERIFY(smallPathsData.open(QIODevice::ReadOnly)); - smallFilePaths = QString::fromLatin1(smallPathsData.readAll()).split(QLatin1Char('\n')); - Q_ASSERT(!smallFilePaths.isEmpty()); - } - - QTest::newRow("paths-small") << smallFilePaths; - } - - { - // list of UUIDs - static QStringList uuids; - if (uuids.isEmpty()) { - // guaranteed to be completely random, generated by http://xkcd.com/221/ - QUuid ns = QUuid("{f43d2ef3-2fe9-4563-a6f5-5a0100c2d699}"); - uuids.reserve(smallFilePaths.size()); - - foreach (const QString &path, smallFilePaths) - uuids.append(QUuid::createUuidV5(ns, path).toString()); - } - - QTest::newRow("uuids-list") << uuids; - } - - { - // lots of strings with alphabetical characters, vaguely reminiscent of - // a dictionary. - // - // this programatically generates a series like: - // AAAAAA - // AAAAAB - // AAAAAC - // ... - // AAAAAZ - // AAAABZ - // ... - // AAAAZZ - // AAABZZ - QByteArray id("AAAAAAA"); - static QStringList dict; - - if (dict.isEmpty()) { - for (int i = id.length() - 1; i > 0;) { - dict.append(id); - char c = id.at(i); - id[i] = ++c; - - if (c == 'Z') { - // wrap to next digit - i--; - id[i] = 'A'; - } + // small list of file paths + QFile smallPathsData("paths_small_data.txt"); + QVERIFY(smallPathsData.open(QIODevice::ReadOnly)); + smallFilePaths = QString::fromLatin1(smallPathsData.readAll()).split(QLatin1Char('\n')); + QVERIFY(!smallFilePaths.isEmpty()); + + // list of UUIDs + // guaranteed to be completely random, generated by http://xkcd.com/221/ + QUuid ns = QUuid("{f43d2ef3-2fe9-4563-a6f5-5a0100c2d699}"); + uuids.reserve(smallFilePaths.size()); + + foreach (const QString &path, smallFilePaths) + uuids.append(QUuid::createUuidV5(ns, path).toString()); + + + // lots of strings with alphabetical characters, vaguely reminiscent of + // a dictionary. + // + // this programatically generates a series like: + // AAAAAA + // AAAAAB + // AAAAAC + // ... + // AAAAAZ + // AAAABZ + // ... + // AAAAZZ + // AAABZZ + QByteArray id("AAAAAAA"); + + if (dict.isEmpty()) { + for (int i = id.length() - 1; i > 0;) { + dict.append(id); + char c = id.at(i); + id[i] = ++c; + + if (c == 'Z') { + // wrap to next digit + i--; + id[i] = 'A'; } } - - QTest::newRow("dictionary") << dict; } - { - // string versions of numbers. - static QStringList numbers; - - if (numbers.isEmpty()) { - for (int i = 5000000; i < 5005001; ++i) - numbers.append(QString::number(i)); - } - - QTest::newRow("numbers") << numbers; - } + // string versions of numbers. + for (int i = 5000000; i < 5005001; ++i) + numbers.append(QString::number(i)); +} +void tst_QHash::data() +{ + QTest::addColumn("items"); + QTest::newRow("paths-small") << smallFilePaths; + QTest::newRow("uuids-list") << uuids; + QTest::newRow("dictionary") << dict; + QTest::newRow("numbers") << numbers; } void tst_QHash::qhash_qt4() -- cgit v1.2.3 From 1f4804452c05c57308979bf090305c7c882f92c9 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 28 Feb 2012 20:56:14 +0100 Subject: Copy Qt 4's QString hash algorithm. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We must do this the same way we do all other hash algorithms for fair comparison, as otherwise, the call to the PLT unfairly penalises QHash's results, as it's in a different shared object. Change-Id: I69c891f5a97dcccdfcfbdbf32796f86242a42963 Reviewed-by: João Abecasis Reviewed-by: Thiago Macieira --- tests/benchmarks/corelib/tools/qhash/main.cpp | 7 +++++-- tests/benchmarks/corelib/tools/qhash/main.h | 11 +++++++++++ tests/benchmarks/corelib/tools/qhash/outofline.cpp | 18 ++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/tests/benchmarks/corelib/tools/qhash/main.cpp b/tests/benchmarks/corelib/tools/qhash/main.cpp index 7a871b455c..62384fbaa7 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.cpp +++ b/tests/benchmarks/corelib/tools/qhash/main.cpp @@ -138,8 +138,11 @@ void tst_QHash::data() void tst_QHash::qhash_qt4() { QFETCH(QStringList, items); - QStringList realitems = items; // for copy/paste ease between benchmarks - QHash hash; + QHash hash; + + QList realitems; + foreach (const QString &s, items) + realitems.append(s); QBENCHMARK { for (int i = 0, n = realitems.size(); i != n; ++i) { diff --git a/tests/benchmarks/corelib/tools/qhash/main.h b/tests/benchmarks/corelib/tools/qhash/main.h index c4cf94e190..3d193b5e40 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.h +++ b/tests/benchmarks/corelib/tools/qhash/main.h @@ -41,6 +41,17 @@ #include +struct Qt4String : QString +{ + Qt4String() {} + Qt4String(const QString &s) : QString(s) {} +}; + +QT_BEGIN_NAMESPACE +uint qHash(const Qt4String &); +QT_END_NAMESPACE + + struct String : QString { String() {} diff --git a/tests/benchmarks/corelib/tools/qhash/outofline.cpp b/tests/benchmarks/corelib/tools/qhash/outofline.cpp index 162c604a35..8adaa0a04f 100644 --- a/tests/benchmarks/corelib/tools/qhash/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qhash/outofline.cpp @@ -41,6 +41,22 @@ #include "main.h" +QT_BEGIN_NAMESPACE + +uint qHash(const Qt4String &str) +{ + int n = str.length(); + const QChar *p = str.unicode(); + uint h = 0; + + while (n--) { + h = (h << 4) + (*p++).unicode(); + h ^= (h & 0xf0000000) >> 23; + h &= 0x0fffffff; + } + return h; +} + static void doHash(const unsigned short *p, uint &h) { #if 1 @@ -67,8 +83,6 @@ static void doHash(const unsigned short *p, uint &h) #endif } -QT_BEGIN_NAMESPACE - uint qHash(const String &str) { const unsigned short *p = (unsigned short *)str.constData(); -- cgit v1.2.3 From b147da00c5fec9d89a2b60d10e82ac28766e2a5b Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 28 Feb 2012 21:04:53 +0100 Subject: Remove qhash_faster. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not faster under _any_ metric than the new algorithm, and it loses a lot of spread which is a bad thing. Change-Id: Ic87258f1c887822ffea1cb1517355564fabc3c26 Reviewed-by: João Abecasis --- tests/benchmarks/corelib/tools/qhash/main.cpp | 18 --------- tests/benchmarks/corelib/tools/qhash/main.h | 11 ------ tests/benchmarks/corelib/tools/qhash/outofline.cpp | 44 ---------------------- 3 files changed, 73 deletions(-) diff --git a/tests/benchmarks/corelib/tools/qhash/main.cpp b/tests/benchmarks/corelib/tools/qhash/main.cpp index 62384fbaa7..67396ffd57 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.cpp +++ b/tests/benchmarks/corelib/tools/qhash/main.cpp @@ -57,8 +57,6 @@ private slots: void initTestCase(); void qhash_qt4_data() { data(); } void qhash_qt4(); - void qhash_faster_data() { data(); } - void qhash_faster(); void javaString_data() { data(); } void javaString(); @@ -151,22 +149,6 @@ void tst_QHash::qhash_qt4() } } -void tst_QHash::qhash_faster() -{ - QFETCH(QStringList, items); - QHash hash; - - QList realitems; - foreach (const QString &s, items) - realitems.append(s); - - QBENCHMARK { - for (int i = 0, n = realitems.size(); i != n; ++i) { - hash[realitems.at(i)] = i; - } - } -} - void tst_QHash::javaString() { QFETCH(QStringList, items); diff --git a/tests/benchmarks/corelib/tools/qhash/main.h b/tests/benchmarks/corelib/tools/qhash/main.h index 3d193b5e40..a865eaf7a6 100644 --- a/tests/benchmarks/corelib/tools/qhash/main.h +++ b/tests/benchmarks/corelib/tools/qhash/main.h @@ -52,17 +52,6 @@ uint qHash(const Qt4String &); QT_END_NAMESPACE -struct String : QString -{ - String() {} - String(const QString &s) : QString(s) {} -}; - -QT_BEGIN_NAMESPACE -uint qHash(const String &); -QT_END_NAMESPACE - - struct JavaString : QString { JavaString() {} diff --git a/tests/benchmarks/corelib/tools/qhash/outofline.cpp b/tests/benchmarks/corelib/tools/qhash/outofline.cpp index 8adaa0a04f..75d99f96f8 100644 --- a/tests/benchmarks/corelib/tools/qhash/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qhash/outofline.cpp @@ -57,50 +57,6 @@ uint qHash(const Qt4String &str) return h; } -static void doHash(const unsigned short *p, uint &h) -{ -#if 1 - // Copied from static uint hash(const QChar *p, int n). - // Possibly not the cheapest way. - h = (h << 4) + (*p++); - h ^= (h & 0xf0000000) >> 23; - h &= 0x0fffffff; - - h = (h << 4) + (*p++); - h ^= (h & 0xf0000000) >> 23; - h &= 0x0fffffff; - - h = (h << 4) + (*p++); - h ^= (h & 0xf0000000) >> 23; - h &= 0x0fffffff; - - h = (h << 4) + (*p++); - h ^= (h & 0xf0000000) >> 23; - h &= 0x0fffffff; -#else - // Faster, but probably less spread. - h ^= *(unsigned int *)p; -#endif -} - -uint qHash(const String &str) -{ - const unsigned short *p = (unsigned short *)str.constData(); - const int s = str.size(); - switch (s) { - case 0: return 0; - case 1: return *p; - case 2: return *(unsigned int *)p; - case 3: return (*(unsigned int *)p) ^ *(p + 2); - //case 3: return (*p << 11) + (*(p + 1) << 22) + *(p + 2); - } - uint h = 0; - doHash(p, h); - doHash(p + s / 2 - 2, h); - doHash(p + s - 4, h); - return h; -} - // The Java's hashing algorithm for strings is a variation of D. J. Bernstein // hashing algorithm appeared here http://cr.yp.to/cdb/cdb.txt // and informally known as DJB33XX - DJB's 33 Times Xor. -- cgit v1.2.3 From ff004175bcd5dc23f8c080cd390b04117c9f51df Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 26 Feb 2012 23:01:46 +0100 Subject: QFlags: mark as Q_PRIMITIVE_TYPE I originally tried to put Q_DECLARE_TYPEINFOs into Q_DECLARE_OPERATORS_FOR_FLAGS, to declare not only the flags type, but also the underlying enum as primitive, but too many users (arguably correctly) used Q_DECLARE_OPERATORS_FOR_FLAGS at (non-global) namespace scope where QTypeInfo would have been specialised in the wrong namespace. So specialise QTypeInfo for QFlags only. Change-Id: I4af6e29aefbd9460a3d2bc6405f03cdf6b1096bc Reviewed-by: Thiago Macieira Reviewed-by: Stephen Kelly Reviewed-by: Olivier Goffart --- src/corelib/global/qtypeinfo.h | 4 ++++ tests/auto/corelib/global/qflags/tst_qflags.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 6297b35b9c..815be935f7 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -161,6 +161,10 @@ public: \ template<> \ Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) +/* Specialize QTypeInfo for QFlags */ +template class QFlags; +template +Q_DECLARE_TYPEINFO_BODY(QFlags, Q_PRIMITIVE_TYPE); /* Specialize a shared type with: diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index d466d7b8d8..2794c174ba 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -123,6 +123,15 @@ void tst_QFlags::constExpr() #endif } +// (statically) check QTypeInfo for QFlags instantiations: +enum MyEnum { Zero, One, Two, Four=4 }; +Q_DECLARE_FLAGS( MyFlags, MyEnum ); +Q_DECLARE_OPERATORS_FOR_FLAGS( MyFlags ); + +Q_STATIC_ASSERT( !QTypeInfo::isComplex ); +Q_STATIC_ASSERT( !QTypeInfo::isStatic ); +Q_STATIC_ASSERT( !QTypeInfo::isLarge ); +Q_STATIC_ASSERT( !QTypeInfo::isPointer ); QTEST_MAIN(tst_QFlags) #include "tst_qflags.moc" -- cgit v1.2.3 From 46e4a9d5231e2d9e35424259858713ca539b8e30 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 20 Feb 2012 18:48:10 +0000 Subject: Windows - fix getsockopt calls for narrower than int options Windows unhelpfully writes to only one byte of the output buffer when getsockopt is called for a boolean option. Therefore we have to zero initialise the int rather than initialising to -1 as was done before. This in general only works for little endian architecture, because the word would look like 0x01000000 on big endian. So I have added some compile time asserts in the assumption that windows is always little endian. This is ok for comparisons with 0/false, but not comparisons with true or nonzero values. In the case of IPV6_V6ONLY, it is documented as DWORD (unsigned int) but on some windows versions it is returned as a boolean triggering the warning. I removed the warning, as the conversion to int works on both LE and BE since it is only compared with zero. Task-number: QTBUG-23488 Change-Id: I3c586d1ada76465fc045a82661f289920c657a4c Reviewed-by: Richard J. Moore Reviewed-by: Friedemann Kleint Reviewed-by: Andreas Holzammer --- src/network/socket/qnativesocketengine_win.cpp | 12 +++++--- .../network/socket/qtcpsocket/tst_qtcpsocket.cpp | 36 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index d7bbe7eb86..93a470c77f 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -427,10 +427,14 @@ int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) co break; } - int v = -1; +#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN +#error code assumes windows is little endian +#endif + int v = 0; //note: windows doesn't write to all bytes if the option type is smaller than int QT_SOCKOPTLEN_T len = sizeof(v); - if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1) + if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0) return v; + WS_ERROR_DEBUG(WSAGetLastError()); return -1; } @@ -563,12 +567,10 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() #if defined (IPV6_V6ONLY) // determine if local address is dual mode DWORD ipv6only = 0; - int optlen = sizeof(ipv6only); + QT_SOCKOPTLEN_T optlen = sizeof(ipv6only); if (localAddress == QHostAddress::AnyIPv6 && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0 && !getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, &optlen )) { - if (optlen != sizeof(ipv6only)) - qWarning("unexpected size of IPV6_V6ONLY socket option"); if (!ipv6only) { socketProtocol = QAbstractSocket::AnyIPProtocol; localAddress = QHostAddress::Any; diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 2c2b551257..8b65c312bc 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -201,6 +201,8 @@ private slots: void qtbug14268_peek(); + void setSocketOption(); + protected slots: void nonBlockingIMAP_hostFound(); @@ -2699,7 +2701,41 @@ void tst_QTcpSocket::qtbug14268_peek() QVERIFY(incoming->read(128*1024) == QByteArray("abc\ndef\nghi\n")); } +void tst_QTcpSocket::setSocketOption() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + SocketPair socketPair; + QVERIFY(socketPair.create()); + QTcpSocket *outgoing = socketPair.endPoints[0]; + QTcpSocket *incoming = socketPair.endPoints[1]; + + QVERIFY(incoming->state() == QTcpSocket::ConnectedState); + QVERIFY(outgoing->state() == QTcpSocket::ConnectedState); + + outgoing->setSocketOption(QAbstractSocket::LowDelayOption, true); + QVariant v = outgoing->socketOption(QAbstractSocket::LowDelayOption); + QVERIFY(v.isValid() && v.toBool()); + outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, true); + v = outgoing->socketOption(QAbstractSocket::KeepAliveOption); + QVERIFY(v.isValid() && v.toBool()); + outgoing->setSocketOption(QAbstractSocket::LowDelayOption, false); + v = outgoing->socketOption(QAbstractSocket::LowDelayOption); + QVERIFY(v.isValid() && !v.toBool()); + outgoing->setSocketOption(QAbstractSocket::KeepAliveOption, false); + v = outgoing->socketOption(QAbstractSocket::KeepAliveOption); + QVERIFY(v.isValid() && !v.toBool()); + +#ifdef Q_OS_WIN + QEXPECT_FAIL("", "QTBUG-23323", Abort); +#endif + outgoing->setSocketOption(QAbstractSocket::TypeOfServiceOption, 32); //high priority + v = outgoing->socketOption(QAbstractSocket::TypeOfServiceOption); + QVERIFY(v.isValid() && v.toInt() == 32); +} QTEST_MAIN(tst_QTcpSocket) #include "tst_qtcpsocket.moc" -- cgit v1.2.3 From 221fe8776b4b156dcdf654e1fc5ab0a1e63cfeab Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 26 Jan 2012 22:36:42 +0100 Subject: Add support for XCode 4 into qmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds support for XCode 4 into qmake and also indirectly fixes a couple of problems that are relevant for XCode 3.2 too Task-number: QTBUG-17247 Change-Id: I722470ad1854bd740cbbd28ff4956057a0e1906b Reviewed-by: David Forstenlechner Reviewed-by: Morten Johan Sørvig (cherry picked from commit b5871311457ca97816c0abbb8b935570bbfb657c) Reviewed-by: Oswald Buddenhagen --- mkspecs/macx-xcode/qmake.conf | 2 - qmake/generators/mac/pbuilder_pbx.cpp | 243 ++++++++++++++++++++++++---------- 2 files changed, 172 insertions(+), 73 deletions(-) diff --git a/mkspecs/macx-xcode/qmake.conf b/mkspecs/macx-xcode/qmake.conf index 4cb462696e..de14562039 100644 --- a/mkspecs/macx-xcode/qmake.conf +++ b/mkspecs/macx-xcode/qmake.conf @@ -13,8 +13,6 @@ include(../common/mac.conf) include(../common/gcc-base-macx.conf) include(../common/g++-macx.conf) -QMAKE_CC = -QMAKE_CXX = QMAKE_LINK = QMAKE_LINK_C = QMAKE_LINK_C_SHLIB = diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index b78ebd136d..5d6dee1bb9 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -508,6 +508,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) //HEADER const int pbVersion = pbuilderVersion(); + QStringList buildConfigGroups; + buildConfigGroups << "PROJECT"; + if (pbVersion >= 46) + buildConfigGroups << "TARGET"; + t << "// !$*UTF8*$!" << "\n" << "{" << "\n" << "\t" << writeSettings("archiveVersion", "1", SettingsNoQuote) << ";" << "\n" @@ -810,7 +815,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) QStringList &libdirs = project->values("QMAKE_PBX_LIBPATHS"), &frameworkdirs = project->values("QMAKE_FRAMEWORKPATH"); QString libs[] = { "QMAKE_LFLAGS", "QMAKE_LIBDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS", - "QMAKE_LIBS", QString() }; + "QMAKE_LIBS", "QMAKE_LIBS_PRIVATE", QString() }; for(int i = 0; !libs[i].isNull(); i++) { tmp = project->values(libs[i]); for(int x = 0; x < tmp.count();) { @@ -1014,28 +1019,22 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", escapeFilePath(grp)) << ";" << "\n" << "\t\t" << "};" << "\n"; } - { //INSTALL BUILDPHASE (copy) + if (!project->isEmpty("DESTDIR")) { QString phase_key = keyFor("QMAKE_PBX_TARGET_COPY_PHASE"); - QString destDir = Option::output_dir; - if (!project->isEmpty("QMAKE_ORIG_DESTDIR")) - destDir = project->first("QMAKE_ORIG_DESTDIR"); + QString destDir = project->first("DESTDIR"); destDir = fixForOutput(destDir); destDir = fileInfo(Option::fixPathToLocalOS(destDir)).absoluteFilePath(); - project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key); + project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); t << "\t\t" << phase_key << " = {\n" + << "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";" << "\n" << "\t\t\t" << writeSettings("name", "Project Copy") << ";" << "\n" << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";" << "\n" - << "\t\t\t" << writeSettings("dstPath", escapeFilePath(destDir)) << ";" << "\n" - << "\t\t\t" << writeSettings("dstSubfolderSpec", "0", SettingsNoQuote) << ";" << "\n" - << "\t\t\t" << writeSettings("files", keyFor("QMAKE_PBX_TARGET_COPY_FILE"), SettingsAsList, 4) << ";" << "\n" - << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";" << "\n" + << "\t\t\t" << writeSettings("files", QStringList(), SettingsAsList, 4) << ";" << "\n" + << "\t\t\t" << writeSettings("inputPaths", QStringList(), SettingsAsList, 4) << ";" << "\n" + << "\t\t\t" << writeSettings("outputPaths", QStringList(), SettingsAsList, 4) << ";" << "\n" << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";" << "\n" - << "\t\t" << "};\n" - << "\t\t" << keyFor("QMAKE_PBX_TARGET_COPY_FILE") << " = {\n" - << "\t\t\t" << writeSettings("fileRef", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n" - << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";" << "\n" - << "\t\t\t" << "settings = {\n" - << "\t\t\t" << "};\n" + << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";" << "\n" + << "\t\t\t" << writeSettings("shellScript", fixForOutput("cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME " + escapeFilePath(destDir))) << ";" << "\n" << "\t\t" << "};\n"; } //BUNDLE_DATA BUILDPHASE (copy) @@ -1113,6 +1112,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", "Qt Preprocessor Steps") << ";" << "\n" << "\t\t\t" << writeSettings("productName", "Qt Preprocessor Steps") << ";" << "\n" << "\t\t\t" << writeSettings("productReference", keyFor("QMAKE_PBX_PRESCRIPTS_BUILDREFERENCE")) << ";" << "\n"; + if (pbVersion >= 46) + t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST"), SettingsNoQuote) << ";" << "\n"; if(!project->isEmpty("QMAKE_PBX_PRODUCT_TYPE")) t << "\t\t\t" << writeSettings("productType", project->first("QMAKE_PBX_PRODUCT_TYPE")) << ";" << "\n"; else @@ -1217,28 +1218,30 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) t << "\t\t\t\t" << writeSettings("CPLUSPLUS", fixForOutput(findProgram(cCompiler))) << ";" << "\n"; } - t << "\t\t\t\t" << writeSettings("HEADER_SEARCH_PATHS", fixListForOutput("INCLUDEPATH") + QStringList(fixForOutput(specdir())), SettingsAsList, 5) << ";" << "\n" - << "\t\t\t\t" << writeSettings("LIBRARY_SEARCH_PATHS", fixListForOutput("QMAKE_PBX_LIBPATHS"), SettingsAsList, 5) << ";" << "\n" - << "\t\t\t\t" << writeSettings("OPTIMIZATION_CFLAGS", QStringList(), SettingsAsList, 5) << ";" << "\n"; - { - QStringList cflags = fixListForOutput("QMAKE_CFLAGS"); - const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); - for(int i = 0; i < prl_defines.size(); ++i) - cflags += "-D" + prl_defines.at(i); - const QStringList &defines = project->values("DEFINES"); - for(int i = 0; i < defines.size(); ++i) - cflags += "-D" + defines.at(i); - t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", cflags, SettingsAsList, 5) << ";" << "\n"; - } - { - QStringList cxxflags = fixListForOutput("QMAKE_CXXFLAGS"); - const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); - for(int i = 0; i < prl_defines.size(); ++i) - cxxflags += "-D" + prl_defines.at(i); - const QStringList &defines = project->values("DEFINES"); - for(int i = 0; i < defines.size(); ++i) - cxxflags += "-D" + defines.at(i); - t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", cxxflags, SettingsAsList, 5) << ";" << "\n"; + if (pbVersion < 46) { + t << "\t\t\t\t" << writeSettings("HEADER_SEARCH_PATHS", fixListForOutput("INCLUDEPATH") + QStringList(fixForOutput(specdir())), SettingsAsList, 5) << ";" << "\n" + << "\t\t\t\t" << writeSettings("LIBRARY_SEARCH_PATHS", fixListForOutput("QMAKE_PBX_LIBPATHS"), SettingsAsList, 5) << ";" << "\n" + << "\t\t\t\t" << writeSettings("OPTIMIZATION_CFLAGS", QStringList(), SettingsAsList, 5) << ";" << "\n"; + { + QStringList cflags = fixListForOutput("QMAKE_CFLAGS"); + const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); + for (int i = 0; i < prl_defines.size(); ++i) + cflags += "-D" + prl_defines.at(i); + const QStringList &defines = project->values("DEFINES"); + for (int i = 0; i < defines.size(); ++i) + cflags += "-D" + defines.at(i); + t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", cflags, SettingsAsList, 5) << ";" << "\n"; + } + { + QStringList cxxflags = fixListForOutput("QMAKE_CXXFLAGS"); + const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); + for (int i = 0; i < prl_defines.size(); ++i) + cxxflags += "-D" + prl_defines.at(i); + const QStringList &defines = project->values("DEFINES"); + for (int i = 0; i < defines.size(); ++i) + cxxflags += "-D" + defines.at(i); + t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", cxxflags, SettingsAsList, 5) << ";" << "\n"; + } } t << "\t\t\t\t" << writeSettings("LEXFLAGS", fixListForOutput("QMAKE_LEXFLAGS")) << ";" << "\n" << "\t\t\t\t" << writeSettings("YACCFLAGS", fixListForOutput("QMAKE_YACCFLAGS")) << ";" << "\n" @@ -1298,7 +1301,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) + fixListForOutput("QMAKE_LFLAGS") + fixListForOutput("QMAKE_LIBDIR_FLAGS") + fixListForOutput("QMAKE_FRAMEWORKPATH_FLAGS") - + fixListForOutput("QMAKE_LIBS"), + + fixListForOutput("QMAKE_LIBS") + + fixListForOutput("QMAKE_LIBS_PRIVATE"), SettingsAsList, 6) << ";" << "\n"; } if(!project->isEmpty("DESTDIR")) { @@ -1318,7 +1322,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) project->isActiveConfig("lib_bundle")) t << "\t\t\t\t" << writeSettings("FRAMEWORK_VERSION", project->first("QMAKE_FRAMEWORK_VERSION")) << ";" << "\n"; } - if(!project->isEmpty("COMPAT_FRAMEWORKPATH")) + if (pbVersion < 46 && !project->isEmpty("COMPAT_FRAMEWORKPATH")) t << "\t\t\t\t" << writeSettings("FRAMEWORK_SEARCH_PATHS", fixListForOutput("QMAKE_FRAMEWORKPATH"), SettingsAsList, 5) << ";" << "\n"; if(!project->isEmpty("COMPAT_VERSION")) t << "\t\t\t\t" << writeSettings("DYLIB_COMPATIBILITY_VERSION", project->first("COMPAT_VERSION")) << ";" << "\n"; @@ -1334,7 +1338,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) else t << "\t\t\t\t" << writeSettings("SYMROOT", fixForOutput(qmake_getpwd())) << ";" << "\n"; #endif - { + if (pbVersion < 46) { QStringList archs; if(project->isActiveConfig("x86")) archs += "i386"; @@ -1385,6 +1389,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("dependencies", project->values("QMAKE_PBX_TARGET_DEPENDS"), SettingsAsList, 4) << ";" << "\n" << "\t\t\t" << writeSettings("productReference", keyFor(pbx_dir + "QMAKE_PBX_REFERENCE")) << ";" << "\n" << "\t\t\t" << writeSettings("shouldUseHeadermap", "1", SettingsNoQuote) << ";" << "\n"; + if (pbVersion >= 46) + t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST_TARGET"), SettingsNoQuote) << ";" << "\n"; if(pbVersion >= 38) t << "\t\t\t" << writeSettings("isa", "PBXNativeTarget", SettingsNoQuote) << ";" << "\n"; if(project->first("TEMPLATE") == "app") { @@ -1493,6 +1499,16 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) settings.insert(name, value); } } + if (pbVersion >= 46) { + if (project->first("TEMPLATE") == "app") { + settings.insert("PRODUCT_NAME", fixForOutput(project->first("QMAKE_ORIG_TARGET"))); + } else { + QString lib = project->first("QMAKE_ORIG_TARGET"); + if (!project->isActiveConfig("lib_bundle") && !project->isActiveConfig("staticlib")) + lib.prepend("lib"); + settings.insert("PRODUCT_NAME", escapeFilePath(lib)); + } + } QString name; if(pbVersion >= 42) @@ -1500,42 +1516,121 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) else name = (as_release ? "Deployment" : "Development"); if(pbVersion >= 42) { - QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + name); - project->values("QMAKE_PBX_BUILDCONFIGS").append(key); + for (int i = 0; i < buildConfigGroups.size(); i++) { + QString key = keyFor("QMAKE_PBX_BUILDCONFIG_" + name + buildConfigGroups.at(i)); + project->values("QMAKE_PBX_BUILDCONFIGS_" + buildConfigGroups.at(i)).append(key); + t << "\t\t" << key << " = {" << "\n" + << "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";" << "\n" + << "\t\t\t" << "buildSettings = {" << "\n"; + for (QMap::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it) + t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n"; + if (pbVersion >= 46) { + if (buildConfigGroups.at(i) == QLatin1String("PROJECT")) { + t << "\t\t\t\t" << writeSettings("HEADER_SEARCH_PATHS", fixListForOutput("INCLUDEPATH") + QStringList(fixForOutput(specdir())), SettingsAsList, 5) << ";" << "\n" + << "\t\t\t\t" << writeSettings("LIBRARY_SEARCH_PATHS", fixListForOutput("QMAKE_PBX_LIBPATHS"), SettingsAsList, 5) << ";" << "\n" + << "\t\t\t\t" << writeSettings("FRAMEWORK_SEARCH_PATHS", fixListForOutput("QMAKE_FRAMEWORKPATH"), SettingsAsList, 5) << ";" << "\n" + << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", "Info.plist") << ";" << "\n"; + { + QStringList cflags = fixListForOutput("QMAKE_CFLAGS"); + const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); + for (int i = 0; i < prl_defines.size(); ++i) + cflags += "-D" + prl_defines.at(i); + const QStringList &defines = project->values("DEFINES"); + for (int i = 0; i < defines.size(); ++i) + cflags += "-D" + defines.at(i); + t << "\t\t\t\t" << writeSettings("OTHER_CFLAGS", cflags, SettingsAsList, 5) << ";" << "\n"; + } + { + QStringList cxxflags = fixListForOutput("QMAKE_CXXFLAGS"); + const QStringList &prl_defines = project->values("PRL_EXPORT_DEFINES"); + for (int i = 0; i < prl_defines.size(); ++i) + cxxflags += "-D" + prl_defines.at(i); + const QStringList &defines = project->values("DEFINES"); + for (int i = 0; i < defines.size(); ++i) + cxxflags += "-D" + defines.at(i); + t << "\t\t\t\t" << writeSettings("OTHER_CPLUSPLUSFLAGS", cxxflags, SettingsAsList, 5) << ";" << "\n"; + } + if (!project->isActiveConfig("staticlib")) { + t << "\t\t\t\t" << writeSettings("OTHER_LDFLAGS", + fixListForOutput("SUBLIBS") + + fixListForOutput("QMAKE_LFLAGS") + + fixListForOutput("QMAKE_LIBDIR_FLAGS") + + fixListForOutput("QMAKE_FRAMEWORKPATH_FLAGS") + + fixListForOutput("QMAKE_LIBS") + + fixListForOutput("QMAKE_LIBS_PRIVATE"), + SettingsAsList, 6) << ";" << "\n"; + } + { + QStringList archs; + if (project->isActiveConfig("x86")) + archs += "i386"; + if (project->isActiveConfig("ppc")) { + if (!archs.isEmpty()) + archs += " "; + archs += "ppc"; + } + if (project->isActiveConfig("ppc64")) { + if (!archs.isEmpty()) + archs += " "; + archs += "ppc64"; + } + if (project->isActiveConfig("x86_64")) { + if (!archs.isEmpty()) + archs += " "; + archs += "x86_64"; + } + if (!archs.isEmpty()) + t << "\t\t\t\t" << writeSettings("ARCHS", archs) << ";" << "\n"; + } + } else { + if (project->first("TEMPLATE") == "app") { + if (pbVersion < 38 && project->isActiveConfig("app_bundle")) + t << "\t\t\t\t" << writeSettings("WRAPPER_SUFFIX", "app") << ";" << "\n"; + t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", fixForOutput(project->first("QMAKE_ORIG_TARGET"))) << ";" << "\n"; + } else { + if (!project->isActiveConfig("plugin") && project->isActiveConfig("staticlib")) + t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "STATIC") << ";" << "\n"; + else + t << "\t\t\t\t" << writeSettings("LIBRARY_STYLE", "DYNAMIC") << ";" << "\n"; + QString lib = project->first("QMAKE_ORIG_TARGET"); + if (!project->isActiveConfig("lib_bundle") && !project->isActiveConfig("staticlib")) + lib.prepend("lib"); + t << "\t\t\t\t" << writeSettings("PRODUCT_NAME", escapeFilePath(lib)) << ";" << "\n"; + } + } + t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << writeSettings("name", name) << ";" << "\n" + << "\t\t" << "};" << "\n"; + } + } + + QString key = keyFor("QMAKE_PBX_BUILDSTYLE_" + name); + if (project->isActiveConfig("debug") != (bool)as_release) { + project->values("QMAKE_PBX_BUILDSTYLES").append(key); + active_buildstyle = name; + } else if (pbVersion >= 42) { + project->values("QMAKE_PBX_BUILDSTYLES").append(key); + } t << "\t\t" << key << " = {" << "\n" - << "\t\t\t" << writeSettings("isa", "XCBuildConfiguration", SettingsNoQuote) << ";" << "\n" + << "\t\t\t" << writeSettings("buildRules", QStringList(), SettingsAsList, 4) << ";" << "\n" << "\t\t\t" << "buildSettings = {" << "\n"; for(QMap::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it) - t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";\n"; + t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";" << "\n"; t << "\t\t\t" << "};" << "\n" + << "\t\t\t" << writeSettings("isa", "PBXBuildStyle") << ";" << "\n" << "\t\t\t" << writeSettings("name", name) << ";" << "\n" << "\t\t" << "};" << "\n"; } - - QString key = keyFor("QMAKE_PBX_BUILDSTYLE_" + name); - if(project->isActiveConfig("debug") != (bool)as_release) { - project->values("QMAKE_PBX_BUILDSTYLES").append(key); - active_buildstyle = name; - } else if(pbVersion >= 42) { - project->values("QMAKE_PBX_BUILDSTYLES").append(key); - } - t << "\t\t" << key << " = {" << "\n" - << "\t\t\t" << writeSettings("buildRules", QStringList(), SettingsAsList, 4) << ";" << "\n" - << "\t\t\t" << "buildSettings = {" << "\n"; - for(QMap::Iterator set_it = settings.begin(); set_it != settings.end(); ++set_it) - t << "\t\t\t\t" << writeSettings(set_it.key(), set_it.value()) << ";" << "\n"; - t << "\t\t\t" << "};" << "\n" - << "\t\t\t" << writeSettings("isa", "PBXBuildStyle") << ";" << "\n" - << "\t\t\t" << writeSettings("name", name) << ";" << "\n" - << "\t\t" << "};" << "\n"; } if(pbVersion >= 42) { - t << "\t\t" << keyFor("QMAKE_PBX_BUILDCONFIG_LIST") << " = {" << "\n" - << "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n" - << "\t\t\t" << writeSettings("buildConfigurations", project->values("QMAKE_PBX_BUILDCONFIGS"), SettingsAsList, 4) << ";" << "\n" - << "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n" - << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n" - << "\t\t" << "};" << "\n"; + for (int i = 0; i < buildConfigGroups.size(); i++) { + t << "\t\t" << keyFor("QMAKE_PBX_BUILDCONFIG_LIST_" + buildConfigGroups.at(i)) << " = {" << "\n" + << "\t\t\t" << writeSettings("isa", "XCConfigurationList", SettingsNoQuote) << ";" << "\n" + << "\t\t\t" << writeSettings("buildConfigurations", project->values("QMAKE_PBX_BUILDCONFIGS_" + buildConfigGroups.at(i)), SettingsAsList, 4) << ";" << "\n" + << "\t\t\t" << writeSettings("defaultConfigurationIsVisible", "0", SettingsNoQuote) << ";" << "\n" + << "\t\t\t" << writeSettings("defaultConfigurationIsName", active_buildstyle) << ";" << "\n" + << "\t\t" << "};" << "\n"; + } } //ROOT t << "\t\t" << keyFor("QMAKE_PBX_ROOT") << " = {" << "\n" @@ -1544,7 +1639,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("isa", "PBXProject", SettingsNoQuote) << ";" << "\n" << "\t\t\t" << writeSettings("mainGroup", keyFor("QMAKE_PBX_ROOT_GROUP")) << ";" << "\n"; if(pbVersion >= 42) - t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST")) << ";" << "\n"; + t << "\t\t\t" << writeSettings("buildConfigurationList", keyFor("QMAKE_PBX_BUILDCONFIG_LIST_PROJECT")) << ";" << "\n"; t << "\t\t\t" << writeSettings("projectDirPath", QStringList()) << ";" << "\n" << "\t\t\t" << writeSettings("targets", project->values("QMAKE_PBX_TARGETS"), SettingsAsList, 4) << ";" << "\n" << "\t\t" << "};" << "\n"; @@ -1693,7 +1788,11 @@ ProjectBuilderMakefileGenerator::pbuilderVersion() const #ifdef Q_OS_DARWIN ret = QLatin1String("34"); QCFType cfurl; - OSStatus err = LSFindApplicationForInfo(0, CFSTR("com.apple.Xcode"), 0, 0, &cfurl); + // Check for XCode 4 first + OSStatus err = LSFindApplicationForInfo(0, CFSTR("com.apple.dt.Xcode"), 0, 0, &cfurl); + // Now check for XCode 3 + if (err == kLSApplicationNotFoundErr) + err = LSFindApplicationForInfo(0, CFSTR("com.apple.Xcode"), 0, 0, &cfurl); if (err == noErr) { QCFType bundle = CFBundleCreate(0, cfurl); if (bundle) { @@ -1703,7 +1802,9 @@ ProjectBuilderMakefileGenerator::pbuilderVersion() const QStringList versions = QCFString::toQString(str).split(QLatin1Char('.')); int versionMajor = versions.at(0).toInt(); int versionMinor = versions.at(1).toInt(); - if (versionMajor >= 2) { + if (versionMajor >= 3) { + ret = QLatin1String("46"); + } else if (versionMajor >= 2) { ret = QLatin1String("42"); } else if (versionMajor == 1 && versionMinor >= 5) { ret = QLatin1String("39"); -- cgit v1.2.3 From f885a526acbb2d5fd15fe76478bf3faef1570aec Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 29 Feb 2012 01:01:01 +0100 Subject: SHA-2 code does not compile on FreeBSD The code fails to compile with the below error: qcryptographichash.cpp:55: error: conflicting declaration 'typedef quint64 uint64_t' /usr/include/sys/types.h:99: error: 'uint64_t' has a previous declaration as 'typedef __uint64_t uint64_t' FreeBSDs types.h defines the used defines. Maybe it would be less ugly to switch the code to quint*, or use a define to do so, or to have basic os detection for stdint.h, not to include sys/types.h. Change-Id: Ic62ae4b742c1123b4b7e17158d216374e609f59f Reviewed-by: Bradley T. Hughes --- src/corelib/tools/qcryptographichash.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 31a0fdc5e6..3730a6c580 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -52,9 +52,18 @@ from from stdint.h, but since this header is not available on all platforms (MSVC 2008, for example), we need to define them ourselves. */ +#ifndef _UINT64_T_DECLARED typedef QT_PREPEND_NAMESPACE(quint64) uint64_t; +#endif + +#ifndef _UINT32_T_DECLARED typedef QT_PREPEND_NAMESPACE(quint32) uint32_t; +#endif + +#ifndef _UINT8_T_DECLARED typedef QT_PREPEND_NAMESPACE(quint8) uint8_t; +#endif + typedef QT_PREPEND_NAMESPACE(qint16) int_least16_t; // Header from rfc6234 with 1 modification: // sha1.h - commented out '#include ' on line 74 -- cgit v1.2.3 From eafc667136c28fdde28d5dbc775ad978f888aa71 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 29 Feb 2012 00:02:53 +0000 Subject: QRegExp: fix \i \I \c \C \p \P escape sequences Those escape sequences have a special meaning in the XML Schema 1.1 regular expressions, but not in Perl-compatible ones. An escape sequence that has no special meaning should match the escaped character itself; this patch fixes QRegExp's behaviour in that regard (previously, it added a character class matching nothing). Change-Id: I983f923baa7c2ec19938b96353f3a205e6c06d58 Reviewed-by: Andy Shaw Reviewed-by: Thiago Macieira --- src/corelib/tools/qregexp.cpp | 39 ++++++++++++++++-------- tests/auto/corelib/tools/qregexp/tst_qregexp.cpp | 24 +++++++++++++++ 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index d7bcd0edbc..e55144ec4c 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -3015,6 +3015,8 @@ int QRegExpEngine::getEscape() if (xmlSchemaExtensions) { yyCharClass->setNegative(!yyCharClass->negative()); // fall through + } else { + break; } case 'i': if (xmlSchemaExtensions) { @@ -3045,12 +3047,16 @@ int QRegExpEngine::getEscape() yyCharClass->addRange(0xf900, 0xfdcf); yyCharClass->addRange(0xfdf0, 0xfffd); yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); + return Tok_CharClass; + } else { + break; } - return Tok_CharClass; case 'C': if (xmlSchemaExtensions) { yyCharClass->setNegative(!yyCharClass->negative()); // fall through + } else { + break; } case 'c': if (xmlSchemaExtensions) { @@ -3087,12 +3093,16 @@ int QRegExpEngine::getEscape() yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); yyCharClass->addRange(0x0300, 0x036f); yyCharClass->addRange(0x203f, 0x2040); + return Tok_CharClass; + } else { + break; } - return Tok_CharClass; case 'P': if (xmlSchemaExtensions) { yyCharClass->setNegative(!yyCharClass->negative()); // fall through + } else { + break; } case 'p': if (xmlSchemaExtensions) { @@ -3246,8 +3256,10 @@ int QRegExpEngine::getEscape() } else { error(RXERR_CATEGORY); } + return Tok_CharClass; + } else { + break; } - return Tok_CharClass; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'x': @@ -3265,20 +3277,21 @@ int QRegExpEngine::getEscape() return Tok_Char | val; #endif default: - if (prevCh >= '1' && prevCh <= '9') { + break; + } + if (prevCh >= '1' && prevCh <= '9') { #ifndef QT_NO_REGEXP_BACKREF - val = prevCh - '0'; - while (yyCh >= '0' && yyCh <= '9') { - val = (val * 10) + (yyCh - '0'); - yyCh = getChar(); - } - return Tok_BackRef | val; + val = prevCh - '0'; + while (yyCh >= '0' && yyCh <= '9') { + val = (val * 10) + (yyCh - '0'); + yyCh = getChar(); + } + return Tok_BackRef | val; #else - error(RXERR_DISABLED); + error(RXERR_DISABLED); #endif - } - return Tok_Char | prevCh; } + return Tok_Char | prevCh; } #ifndef QT_NO_REGEXP_INTERVAL diff --git a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp index a697e23270..2995c18dc9 100644 --- a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp +++ b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp @@ -81,6 +81,7 @@ private slots: void interval(); void validityCheck_data(); void validityCheck(); + void escapeSequences(); }; // Testing get/set functions @@ -1373,6 +1374,29 @@ void tst_QRegExp::validityCheck() QCOMPARE(rx2.cap(), QString("")); } +void tst_QRegExp::escapeSequences() +{ + QString perlSyntaxSpecialChars("0123456789afnrtvbBdDwWsSx\\|[]{}()^$?+*"); + QString w3cXmlSchema11SyntaxSpecialChars("cCiIpP"); // as well as the perl ones + for (int i = ' '; i <= 127; ++i) { + QLatin1Char c(i); + if (perlSyntaxSpecialChars.indexOf(c) == -1) { + QRegExp rx(QString("\\%1").arg(c), Qt::CaseSensitive, QRegExp::RegExp); + // we'll never have c == 'a' since it's a special character + QString s = QString("aaa%1aaa").arg(c); + QCOMPARE(rx.indexIn(s), 3); + + rx.setPatternSyntax(QRegExp::RegExp2); + QCOMPARE(rx.indexIn(s), 3); + + if (w3cXmlSchema11SyntaxSpecialChars.indexOf(c) == -1) { + rx.setPatternSyntax(QRegExp::W3CXmlSchema11); + QCOMPARE(rx.indexIn(s), 3); + } + } + } +} + QTEST_APPLESS_MAIN(tst_QRegExp) #include "tst_qregexp.moc" -- cgit v1.2.3 From fb4dccee9a8d616ec43390f855caca08594d75b8 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 12:57:34 +0100 Subject: Fix build of QNetworkReply benchmark with QT_USE_QSTRINGBUILDER. Change-Id: Ie46126aed0d2e83dc7784c027066c789d3fd7652 Reviewed-by: Olivier Goffart --- tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp index fe9efa55b7..16f9625eba 100644 --- a/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/benchmarks/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -530,7 +530,7 @@ void tst_qnetworkreply::downloadPerformance() // unlike the above function, this one tries to send as fast as possible // and measures how fast it was. TimedSender sender(5000); - QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(sender.serverPort()) + "/?bare=1"); + QNetworkRequest request(QUrl(QStringLiteral("debugpipe://127.0.0.1:") + QString::number(sender.serverPort()) + QStringLiteral("/?bare=1"))); QNetworkReplyPtr reply = manager.get(request); DataReader reader(reply, false); @@ -552,7 +552,7 @@ void tst_qnetworkreply::uploadPerformance() DataGenerator generator; - QNetworkRequest request("debugpipe://127.0.0.1:" + QString::number(reader.serverPort()) + "/?bare=1"); + QNetworkRequest request(QUrl(QStringLiteral("debugpipe://127.0.0.1:") + QString::number(reader.serverPort()) + QStringLiteral("/?bare=1"))); QNetworkReplyPtr reply = manager.put(request, &generator); generator.start(); connect(&reader, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); -- cgit v1.2.3 From 5dd470aca683e93976b314388e0d9f7d959db7a4 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 1 Mar 2012 09:06:13 +1000 Subject: Fixed qdir unittest rename() test to skip if run as root - subtest not valid if run as root so added a check and skip Change-Id: Iae993e20f272f9303a75062ef00d22b49df5e84a Reviewed-by: Rohan McGovern --- tests/auto/corelib/io/qdir/tst_qdir.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 04967d8313..ca01a1ec80 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -1231,7 +1231,13 @@ void tst_QDir::rename() QVERIFY(!dir.rename("rename-test", "/etc/rename-test-renamed")); #elif !defined(Q_OS_WIN) // on windows this is possible - maybe make the test a bit better +#ifdef Q_OS_UNIX + // not valid if run as root so skip if needed + if (::getuid() != 0) + QVERIFY(!dir.rename("rename-test", "/rename-test-renamed")); +#else QVERIFY(!dir.rename("rename-test", "/rename-test-renamed")); +#endif #endif QTest::ignoreMessage(QtWarningMsg, "QDir::rename: Empty or null file name(s)"); QVERIFY(!dir.rename("rename-test", "")); -- cgit v1.2.3 From bc323b6fd3e80fd0c9d6a856b0a55c03d08164db Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 1 Mar 2012 12:46:34 +1000 Subject: Changed qlogging unittest to install subprogram - Added install of app sub program so it works from install directory Change-Id: Ia83643519752a3cbb59d6da2aed132d683a94bee Reviewed-by: Rohan McGovern --- tests/auto/corelib/global/qlogging/test/test.pro | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/corelib/global/qlogging/test/test.pro b/tests/auto/corelib/global/qlogging/test/test.pro index 6e4939ffc9..6e9b86d753 100644 --- a/tests/auto/corelib/global/qlogging/test/test.pro +++ b/tests/auto/corelib/global/qlogging/test/test.pro @@ -2,3 +2,6 @@ CONFIG += testcase parallel_test TARGET = ../tst_qlogging QT = core testlib SOURCES = ../tst_qlogging.cpp + +load(testcase) # for target.path and installTestHelperApp() +installTestHelperApp("../app/app",app,app) -- cgit v1.2.3 From 41b29924227214424e526386f11dd0dcca1ebb11 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 1 Mar 2012 12:57:37 +1000 Subject: Changed qdir unittest remove() to check actual file removed - Changed remove() test to check the file just removed is gone. Change-Id: I0b6c176e624134402b5547866064f436ce063f16 Reviewed-by: Rohan McGovern --- tests/auto/corelib/io/qdir/tst_qdir.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index ca01a1ec80..b7fc366a39 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -1214,7 +1214,8 @@ void tst_QDir::remove() f.close(); QDir dir; QVERIFY(dir.remove("remove-test")); - QVERIFY(!dir.remove("/remove-test")); + // Test that the file just removed is gone + QVERIFY(!dir.remove("remove-test")); QTest::ignoreMessage(QtWarningMsg, "QDir::remove: Empty or null file name"); QVERIFY(!dir.remove("")); } -- cgit v1.2.3 From c5b928207ec33417933ee8c03ece8e79db9934f4 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 1 Mar 2012 13:33:40 +1000 Subject: Fixed qlocale unittest to install subprogram syslocaleapp correctly - It was trying to install syslocaleapp sub program as TESTDATA instead of an application. Change-Id: I2117d11335bc2fd37a8ccc9a03b0337382f0177f Reviewed-by: Rohan McGovern --- tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro | 3 --- tests/auto/corelib/tools/qlocale/test/test.pro | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro b/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro index a97350ca3f..b61f51d53a 100644 --- a/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro +++ b/tests/auto/corelib/tools/qlocale/syslocaleapp/syslocaleapp.pro @@ -6,6 +6,3 @@ CONFIG -= app_bundle QT = core -# This app is testdata for tst_qlocale -target.path = $$[QT_INSTALL_TESTS]/tst_qlocale/$$TARGET -INSTALLS += target diff --git a/tests/auto/corelib/tools/qlocale/test/test.pro b/tests/auto/corelib/tools/qlocale/test/test.pro index eafd8c1699..24dcc0638a 100644 --- a/tests/auto/corelib/tools/qlocale/test/test.pro +++ b/tests/auto/corelib/tools/qlocale/test/test.pro @@ -12,6 +12,8 @@ win32 { TARGET = ../../release/tst_qlocale } } -TESTDATA += syslocaleapp + +load(testcase) # for target.path and installTestHelperApp() +installTestHelperApp("../syslocaleapp/syslocaleapp",syslocaleapp,syslocaleapp) mac: CONFIG += insignificant_test # QTBUG-22769 -- cgit v1.2.3 From 95c5be8bc1c8f9ff8e7f95e52a8abd3cd7976ba1 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Thu, 1 Mar 2012 13:18:21 +1000 Subject: Changed qchar unittest to check return from QFINDTESTDATA - Changed qchar unittest to check string QFINDTESTDATA returns is not empty. Change-Id: Idb3997aaa5d5220272915c1e2538175205b3d6e8 Reviewed-by: Rohan McGovern --- tests/auto/corelib/tools/qchar/tst_qchar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/tools/qchar/tst_qchar.cpp index 1732f628ea..e72af11fbb 100644 --- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp +++ b/tests/auto/corelib/tools/qchar/tst_qchar.cpp @@ -580,7 +580,9 @@ void tst_QChar::normalization_data() int linenum = 0; int part = 0; - QFile f(QFINDTESTDATA("NormalizationTest.txt")); + QString testFile = QFINDTESTDATA("NormalizationTest.txt"); + QVERIFY2(!testFile.isEmpty(), "NormalizationTest.txt not found!"); + QFile f(testFile); QVERIFY(f.exists()); f.open(QIODevice::ReadOnly); -- cgit v1.2.3 From 8bf2c470806fb555e8b687ae1eeba31a788e6f76 Mon Sep 17 00:00:00 2001 From: Caroline Chao Date: Wed, 29 Feb 2012 09:21:03 +0100 Subject: CodeCoverage: Exclude all header files from intrumentation. Currently only a small fraction of all the headers are included since only the headers found in the pro file folder are included. This is confusing and arbitrary. With this change all the headers are now excluded from the instrumentation. Change-Id: If4322421f3b3e5fcd45f006421690eaa6bf645e0 Reviewed-by: Rohan McGovern --- mkspecs/features/testcocoon.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/testcocoon.prf b/mkspecs/features/testcocoon.prf index e6ad733540..523497dba1 100644 --- a/mkspecs/features/testcocoon.prf +++ b/mkspecs/features/testcocoon.prf @@ -11,10 +11,10 @@ TARGET_BASENAME = $$basename(QMAKE_RESOLVED_TARGET) # --cs-output defines the name to give to the execution report (.csexe). TESTCOCOON_COVERAGE_OPTIONS = \ --cs-qt4 \ - --cs-exclude-file-regex=\'(^|[/\\\\])ui_.*\\.h\$\$\' \ --cs-exclude-file-regex=\'(^|[/\\\\])(qrc|moc)_.*\\.cpp\$\$\' \ --cs-exclude-file-regex=\'.*\\.moc\$\$\' \ --cs-exclude-file-regex=\'.*\\.g\$\$\' \ + --cs-exclude-file-regex=\'.*\\.h\$\$\' \ --cs-output=\'$$TARGET_BASENAME\' # name of the csexe file (execution report) # The .csmes file should be placed alongside the .so or binary. -- cgit v1.2.3 From ba5dd0d6c04233fa08aaa1a1813b0c122199c7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 15 Feb 2012 17:08:20 +0100 Subject: Added QPlatformScreenBuffer And moved the pageflipper into its own file Done with: Paul Change-Id: I0af34075ce8673a66025cb761c0fe4ff6c0ab0fe Reviewed-by: Jason Barron --- src/gui/kernel/kernel.pri | 6 +- src/gui/kernel/qplatformscreen_qpa.h | 11 +-- src/gui/kernel/qplatformscreenpageflipper_qpa.cpp | 83 +++++++++++++++++++++ src/gui/kernel/qplatformscreenpageflipper_qpa.h | 87 +++++++++++++++++++++++ 4 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 src/gui/kernel/qplatformscreenpageflipper_qpa.cpp create mode 100644 src/gui/kernel/qplatformscreenpageflipper_qpa.h diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 2656d8ffdb..06773f58b5 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -56,7 +56,8 @@ HEADERS += \ kernel/qtouchdevice_p.h \ kernel/qplatformsharedgraphicscache_qpa.h \ kernel/qplatformdialoghelper_qpa.h \ - kernel/qplatformservices_qpa.h + kernel/qplatformservices_qpa.h \ + kernel/qplatformscreenpageflipper_qpa.h SOURCES += \ kernel/qclipboard_qpa.cpp \ @@ -100,7 +101,8 @@ SOURCES += \ kernel/qtouchdevice.cpp \ kernel/qplatformsharedgraphicscache_qpa.cpp \ kernel/qplatformdialoghelper_qpa.cpp \ - kernel/qplatformservices_qpa.cpp + kernel/qplatformservices_qpa.cpp \ + kernel/qplatformscreenpageflipper_qpa.cpp contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, egl) { HEADERS += \ diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h index e4b9b762b1..7d74698074 100644 --- a/src/gui/kernel/qplatformscreen_qpa.h +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -63,21 +63,12 @@ class QPlatformBackingStore; class QPlatformOpenGLContext; class QPlatformScreenPrivate; class QPlatformWindow; +class QPlatformScreenPageFlipper; class QScreen; class QSurfaceFormat; typedef QPair QDpi; -class Q_GUI_EXPORT QPlatformScreenPageFlipper : public QObject -{ - Q_OBJECT -public: - virtual bool displayBuffer(void *bufferHandle) = 0; - - signals: - void bufferDisplayed(void *bufferHandle); - void bufferReleased(void *bufferHandle); -}; class Q_GUI_EXPORT QPlatformScreen { diff --git a/src/gui/kernel/qplatformscreenpageflipper_qpa.cpp b/src/gui/kernel/qplatformscreenpageflipper_qpa.cpp new file mode 100644 index 0000000000..d652e34e5e --- /dev/null +++ b/src/gui/kernel/qplatformscreenpageflipper_qpa.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformscreenpageflipper_qpa.h" + +QT_BEGIN_NAMESPACE + +QPlatformScreenBuffer::QPlatformScreenBuffer() + : m_destroyed(false) + , m_ready(true) +{ + +} + +QPlatformScreenBuffer::~QPlatformScreenBuffer() +{ + +} + +bool QPlatformScreenBuffer::isDestroyed() const +{ + return m_destroyed; +} + +bool QPlatformScreenBuffer::isReady() const +{ + return m_ready; +} + +void QPlatformScreenBuffer::aboutToBeDisplayed() +{ +} + +void QPlatformScreenBuffer::displayed() +{ +} + +QPlatformScreenPageFlipper::QPlatformScreenPageFlipper(QObject *parent) + :QObject(parent) +{ + +} + +QT_END_NAMESPACE + diff --git a/src/gui/kernel/qplatformscreenpageflipper_qpa.h b/src/gui/kernel/qplatformscreenpageflipper_qpa.h new file mode 100644 index 0000000000..850f9d8d2f --- /dev/null +++ b/src/gui/kernel/qplatformscreenpageflipper_qpa.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMSCREENPAGEFLIPPER_QPA_H +#define QPLATFORMSCREENPAGEFLIPPER_QPA_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QPlatformScreenBuffer { +public: + QPlatformScreenBuffer(); + virtual ~QPlatformScreenBuffer(); + + bool isDestroyed() const; + bool isReady() const; + + virtual void aboutToBeDisplayed(); + virtual void displayed(); + virtual void release() = 0; + + virtual void *handle() const = 0; + +protected: + bool m_destroyed; + bool m_ready; +}; + +class Q_GUI_EXPORT QPlatformScreenPageFlipper : public QObject +{ + Q_OBJECT +public: + explicit QPlatformScreenPageFlipper(QObject *parent = 0); + + virtual bool displayBuffer(QPlatformScreenBuffer *) = 0; + +signals: + void bufferDisplayed(QPlatformScreenBuffer *); + void bufferReleased(QPlatformScreenBuffer *); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMSCREENPAGEFLIPPER_QPA_H -- cgit v1.2.3 From 1cd4d6b1819f67b70dd359c7fc43ab06182cc34b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 29 Feb 2012 00:00:27 +0100 Subject: QEvent (and subclasses): make ctors explicit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do this regardless of whether the event subclass is public API or only used in examples. Examples are examples, used by others as templates or even copied verbatim, so they should also follow sound engineering rules. Anyway, there's only one in examples/... Change-Id: I586ff16407a956c9e89288fdd4377eed73f45c0f Reviewed-by: Samuel Rødal --- examples/animation/moveblocks/main.cpp | 2 +- src/concurrent/qfutureinterface_p.h | 2 +- src/corelib/kernel/qcoreevent.h | 6 ++-- src/corelib/kernel/qeventdispatcher_win_p.h | 2 +- src/gui/kernel/qevent.h | 42 +++++++++++----------- src/widgets/graphicsview/qgraphicssceneevent.h | 14 ++++---- src/widgets/kernel/qgesture.h | 2 +- .../corelib/kernel/qeventloop/tst_qeventloop.cpp | 2 +- tests/auto/other/gestures/tst_gestures.cpp | 2 +- tests/auto/testlib/selftests/alive/qtestalive.cpp | 2 +- .../GraphicsViewBenchmark/widgets/themeevent.cpp | 2 +- .../GraphicsViewBenchmark/widgets/themeevent.h | 2 +- 12 files changed, 40 insertions(+), 40 deletions(-) diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp index 8e7c04e9f0..d807bb63d9 100644 --- a/examples/animation/moveblocks/main.cpp +++ b/examples/animation/moveblocks/main.cpp @@ -50,7 +50,7 @@ public: { } - StateSwitchEvent(int rand) + explicit StateSwitchEvent(int rand) : QEvent(Type(StateSwitchType)), m_rand(rand) { diff --git a/src/concurrent/qfutureinterface_p.h b/src/concurrent/qfutureinterface_p.h index 3a73f846ac..b985e31ab6 100644 --- a/src/concurrent/qfutureinterface_p.h +++ b/src/concurrent/qfutureinterface_p.h @@ -80,7 +80,7 @@ public: QFutureCallOutEvent() : QEvent(QEvent::FutureCallOut), callOutType(CallOutType(0)), index1(-1), index2(-1) { } - QFutureCallOutEvent(CallOutType callOutType, int index1 = -1) + explicit QFutureCallOutEvent(CallOutType callOutType, int index1 = -1) : QEvent(QEvent::FutureCallOut), callOutType(callOutType), index1(index1), index2(-1) { } QFutureCallOutEvent(CallOutType callOutType, int index1, int index2) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 1f36f9c9c8..cac89f2b13 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -288,7 +288,7 @@ public: MaxUser = 65535 // last user event id }; - QEvent(Type type); + explicit QEvent(Type type); virtual ~QEvent(); inline Type type() const { return static_cast(t); } inline bool spontaneous() const { return spont; } @@ -330,7 +330,7 @@ private: class Q_CORE_EXPORT QTimerEvent : public QEvent { public: - QTimerEvent( int timerId ); + explicit QTimerEvent( int timerId ); ~QTimerEvent(); int timerId() const { return id; } protected: @@ -355,7 +355,7 @@ protected: class Q_CORE_EXPORT QDynamicPropertyChangeEvent : public QEvent { public: - QDynamicPropertyChangeEvent(const QByteArray &name); + explicit QDynamicPropertyChangeEvent(const QByteArray &name); ~QDynamicPropertyChangeEvent(); inline QByteArray propertyName() const { return n; } diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a831ad39e8..565f1ef4b3 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -131,7 +131,7 @@ struct WinTimerInfo { // internal timer info class QZeroTimerEvent : public QTimerEvent { public: - inline QZeroTimerEvent(int timerId) + explicit inline QZeroTimerEvent(int timerId) : QTimerEvent(timerId) { t = QEvent::ZeroTimerEvent; } }; diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index ca93095a94..feee7fa837 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -71,7 +71,7 @@ class QScreen; class Q_GUI_EXPORT QInputEvent : public QEvent { public: - QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier); + explicit QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier); ~QInputEvent(); inline Qt::KeyboardModifiers modifiers() const { return modState; } inline void setModifiers(Qt::KeyboardModifiers amodifiers) { modState = amodifiers; } @@ -276,7 +276,7 @@ protected: class Q_GUI_EXPORT QFocusEvent : public QEvent { public: - QFocusEvent(Type type, Qt::FocusReason reason=Qt::OtherFocusReason); + explicit QFocusEvent(Type type, Qt::FocusReason reason=Qt::OtherFocusReason); ~QFocusEvent(); inline bool gotFocus() const { return type() == FocusIn; } @@ -292,8 +292,8 @@ private: class Q_GUI_EXPORT QPaintEvent : public QEvent { public: - QPaintEvent(const QRegion& paintRegion); - QPaintEvent(const QRect &paintRect); + explicit QPaintEvent(const QRegion& paintRegion); + explicit QPaintEvent(const QRect &paintRect); ~QPaintEvent(); inline const QRect &rect() const { return m_rect; } @@ -311,7 +311,7 @@ protected: class Q_GUI_EXPORT QUpdateLaterEvent : public QEvent { public: - QUpdateLaterEvent(const QRegion& paintRegion); + explicit QUpdateLaterEvent(const QRegion& paintRegion); ~QUpdateLaterEvent(); inline const QRegion ®ion() const { return m_region; } @@ -337,7 +337,7 @@ protected: class Q_GUI_EXPORT QExposeEvent : public QEvent { public: - QExposeEvent(const QRegion &rgn); + explicit QExposeEvent(const QRegion &rgn); ~QExposeEvent(); inline const QRegion ®ion() const { return rgn; } @@ -468,7 +468,7 @@ private: class Q_GUI_EXPORT QInputMethodQueryEvent : public QEvent { public: - QInputMethodQueryEvent(Qt::InputMethodQueries queries); + explicit QInputMethodQueryEvent(Qt::InputMethodQueries queries); ~QInputMethodQueryEvent(); Qt::InputMethodQueries queries() const { return m_queries; } @@ -586,7 +586,7 @@ private: class Q_GUI_EXPORT QStatusTipEvent : public QEvent { public: - QStatusTipEvent(const QString &tip); + explicit QStatusTipEvent(const QString &tip); ~QStatusTipEvent(); inline QString tip() const { return s; } @@ -599,7 +599,7 @@ private: class Q_GUI_EXPORT QWhatsThisClickedEvent : public QEvent { public: - QWhatsThisClickedEvent(const QString &href); + explicit QWhatsThisClickedEvent(const QString &href); ~QWhatsThisClickedEvent(); inline QString href() const { return s; } @@ -624,8 +624,8 @@ public: class Q_GUI_EXPORT QFileOpenEvent : public QEvent { public: - QFileOpenEvent(const QString &file); - QFileOpenEvent(const QUrl &url); + explicit QFileOpenEvent(const QString &file); + explicit QFileOpenEvent(const QUrl &url); ~QFileOpenEvent(); inline QString file() const { return f; } @@ -639,7 +639,7 @@ private: class Q_GUI_EXPORT QToolBarChangeEvent : public QEvent { public: - QToolBarChangeEvent(bool t); + explicit QToolBarChangeEvent(bool t); ~QToolBarChangeEvent(); inline bool toggle() const { return tog; } @@ -669,7 +669,7 @@ protected: class Q_GUI_EXPORT QClipboardEvent : public QEvent { public: - QClipboardEvent(QEventPrivate *data); + explicit QClipboardEvent(QEventPrivate *data); ~QClipboardEvent(); QEventPrivate *data() { return d; } @@ -679,7 +679,7 @@ public: class Q_GUI_EXPORT QWindowStateChangeEvent: public QEvent { public: - QWindowStateChangeEvent(Qt::WindowStates aOldState); + explicit QWindowStateChangeEvent(Qt::WindowStates aOldState); QWindowStateChangeEvent(Qt::WindowStates aOldState, bool isOverride); ~QWindowStateChangeEvent(); @@ -711,7 +711,7 @@ public: }; Q_DECLARE_FLAGS(InfoFlags, InfoFlag) - TouchPoint(int id = -1); + explicit TouchPoint(int id = -1); TouchPoint(const QTouchEvent::TouchPoint &other); ~TouchPoint(); @@ -783,11 +783,11 @@ public: }; #endif - QTouchEvent(QEvent::Type eventType, - QTouchDevice *device = 0, - Qt::KeyboardModifiers modifiers = Qt::NoModifier, - Qt::TouchPointStates touchPointStates = 0, - const QList &touchPoints = QList()); + explicit QTouchEvent(QEvent::Type eventType, + QTouchDevice *device = 0, + Qt::KeyboardModifiers modifiers = Qt::NoModifier, + Qt::TouchPointStates touchPointStates = 0, + const QList &touchPoints = QList()); ~QTouchEvent(); inline QWindow *window() const { return _window; } @@ -825,7 +825,7 @@ class QScrollPrepareEventPrivate; class Q_GUI_EXPORT QScrollPrepareEvent : public QEvent { public: - QScrollPrepareEvent(const QPointF &startPos); + explicit QScrollPrepareEvent(const QPointF &startPos); ~QScrollPrepareEvent(); QPointF startPos() const; diff --git a/src/widgets/graphicsview/qgraphicssceneevent.h b/src/widgets/graphicsview/qgraphicssceneevent.h index be93c47476..95de435846 100644 --- a/src/widgets/graphicsview/qgraphicssceneevent.h +++ b/src/widgets/graphicsview/qgraphicssceneevent.h @@ -66,7 +66,7 @@ class QGraphicsSceneEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneEvent : public QEvent { public: - QGraphicsSceneEvent(Type type); + explicit QGraphicsSceneEvent(Type type); ~QGraphicsSceneEvent(); QWidget *widget() const; @@ -84,7 +84,7 @@ class QGraphicsSceneMouseEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneMouseEvent : public QGraphicsSceneEvent { public: - QGraphicsSceneMouseEvent(Type type = None); + explicit QGraphicsSceneMouseEvent(Type type = None); ~QGraphicsSceneMouseEvent(); QPointF pos() const; @@ -132,7 +132,7 @@ class QGraphicsSceneWheelEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneWheelEvent : public QGraphicsSceneEvent { public: - QGraphicsSceneWheelEvent(Type type = None); + explicit QGraphicsSceneWheelEvent(Type type = None); ~QGraphicsSceneWheelEvent(); QPointF pos() const; @@ -167,7 +167,7 @@ class Q_WIDGETS_EXPORT QGraphicsSceneContextMenuEvent : public QGraphicsSceneEve public: enum Reason { Mouse, Keyboard, Other }; - QGraphicsSceneContextMenuEvent(Type type = None); + explicit QGraphicsSceneContextMenuEvent(Type type = None); ~QGraphicsSceneContextMenuEvent(); QPointF pos() const; @@ -194,7 +194,7 @@ class QGraphicsSceneHoverEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneHoverEvent : public QGraphicsSceneEvent { public: - QGraphicsSceneHoverEvent(Type type = None); + explicit QGraphicsSceneHoverEvent(Type type = None); ~QGraphicsSceneHoverEvent(); QPointF pos() const; @@ -227,7 +227,7 @@ class QGraphicsSceneHelpEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneHelpEvent : public QGraphicsSceneEvent { public: - QGraphicsSceneHelpEvent(Type type = None); + explicit QGraphicsSceneHelpEvent(Type type = None); ~QGraphicsSceneHelpEvent(); QPointF scenePos() const; @@ -245,7 +245,7 @@ class QGraphicsSceneDragDropEventPrivate; class Q_WIDGETS_EXPORT QGraphicsSceneDragDropEvent : public QGraphicsSceneEvent { public: - QGraphicsSceneDragDropEvent(Type type = None); + explicit QGraphicsSceneDragDropEvent(Type type = None); ~QGraphicsSceneDragDropEvent(); QPointF pos() const; diff --git a/src/widgets/kernel/qgesture.h b/src/widgets/kernel/qgesture.h index 8c412680b8..5e121def41 100644 --- a/src/widgets/kernel/qgesture.h +++ b/src/widgets/kernel/qgesture.h @@ -270,7 +270,7 @@ class QGestureEventPrivate; class Q_WIDGETS_EXPORT QGestureEvent : public QEvent { public: - QGestureEvent(const QList &gestures); + explicit QGestureEvent(const QList &gestures); ~QGestureEvent(); QList gestures() const; diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp index e2144134d9..61484c1736 100644 --- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp @@ -132,7 +132,7 @@ public: class StartStopEvent: public QEvent { public: - StartStopEvent(int type, QEventLoop *loop = 0) + explicit StartStopEvent(int type, QEventLoop *loop = 0) : QEvent(Type(type)), el(loop) { } diff --git a/tests/auto/other/gestures/tst_gestures.cpp b/tests/auto/other/gestures/tst_gestures.cpp index 01e26b6608..81881fc700 100644 --- a/tests/auto/other/gestures/tst_gestures.cpp +++ b/tests/auto/other/gestures/tst_gestures.cpp @@ -87,7 +87,7 @@ class CustomEvent : public QEvent public: static int EventType; - CustomEvent(int serial_ = 0) + explicit CustomEvent(int serial_ = 0) : QEvent(QEvent::Type(CustomEvent::EventType)), serial(serial_), hasHotSpot(false) { diff --git a/tests/auto/testlib/selftests/alive/qtestalive.cpp b/tests/auto/testlib/selftests/alive/qtestalive.cpp index c2e597ac18..d962b7801f 100644 --- a/tests/auto/testlib/selftests/alive/qtestalive.cpp +++ b/tests/auto/testlib/selftests/alive/qtestalive.cpp @@ -50,7 +50,7 @@ public: enum { AliveEventType = QEvent::User + 422 }; - inline QTestAliveEvent(int aSequenceId) + explicit inline QTestAliveEvent(int aSequenceId) : QEvent(QEvent::Type(AliveEventType)), seqId(aSequenceId) {} inline int sequenceId() const { return seqId; } diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp index 1ebdf2e0bb..3ce3d5c2c1 100644 --- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp +++ b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.cpp @@ -41,7 +41,7 @@ #include "themeevent.h" -ThemeEvent::ThemeEvent( QString newTheme, Type type) : QEvent(type), +ThemeEvent::ThemeEvent( const QString &newTheme, Type type) : QEvent(type), m_theme(newTheme) { diff --git a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h index c98f90da55..3603b5966f 100644 --- a/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h +++ b/tests/benchmarks/gui/graphicsview/functional/GraphicsViewBenchmark/widgets/themeevent.h @@ -50,7 +50,7 @@ static QEvent::Type ThemeEventType = (QEvent::Type) 1010; class ThemeEvent : public QEvent { public: - ThemeEvent(QString newTheme, QEvent::Type type = ThemeEventType ); + explicit ThemeEvent(const QString &newTheme, QEvent::Type type = ThemeEventType ); ~ThemeEvent(); public: -- cgit v1.2.3 From 9e893f68104689b057bffeb57e892163e2561b20 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Mar 2012 09:38:45 +0100 Subject: Skip the network SSL test on Windows. For SSL, this would require an OpenSSL library to be installed. Change-Id: I2a320e7faf40ef925c90dbe539f912e4a8fc13fc Reviewed-by: Miikka Heikkinen Reviewed-by: Sergio Ahumada --- tests/auto/other/networkselftest/tst_networkselftest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/other/networkselftest/tst_networkselftest.cpp b/tests/auto/other/networkselftest/tst_networkselftest.cpp index 841df6e1f0..ebb8443748 100644 --- a/tests/auto/other/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/other/networkselftest/tst_networkselftest.cpp @@ -938,7 +938,7 @@ void tst_NetworkSelfTest::socks5ProxyAuth() void tst_NetworkSelfTest::supportsSsl() { #ifdef QT_NO_SSL - QFAIL("SSL not compiled in"); + QSKIP("SSL not compiled in"); #else QVERIFY2(QSslSocket::supportsSsl(), "Could not load SSL libraries"); #endif -- cgit v1.2.3 From e17440586252551c6de169d9141daef1c31a1e7e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 23:53:20 +0100 Subject: Make some tests and benchmarks pass with QT_NO_QSTRINGBUILDER Change-Id: I6c91a613007043d0f26ac11e98353a0b9ce646ae Reviewed-by: Olivier Goffart --- .../network/kernel/qauthenticator/tst_qauthenticator.cpp | 6 +++--- tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp | 4 ++-- .../corelib/tools/containers-associative/main.cpp | 8 ++++---- .../corelib/tools/containers-sequential/main.cpp | 16 ++++++++-------- tests/benchmarks/dbus/qdbustype/main.cpp | 2 +- tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp index 9c1b8c32f6..7cb5dfd5cd 100644 --- a/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp +++ b/tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp @@ -93,7 +93,7 @@ void tst_QAuthenticator::basicAuth() QVERIFY(priv->phase == QAuthenticatorPrivate::Start); QList > headers; - headers << qMakePair(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8()); + headers << qMakePair(QByteArray("WWW-Authenticate"), "Basic " + data.toUtf8()); priv->parseHttpResponse(headers, /*isProxy = */ false); QCOMPARE(auth.realm(), realm); @@ -104,7 +104,7 @@ void tst_QAuthenticator::basicAuth() QVERIFY(priv->phase == QAuthenticatorPrivate::Start); - QCOMPARE(priv->calculateResponse("GET", "/").constData(), ("Basic " + expectedReply).constData()); + QCOMPARE(priv->calculateResponse("GET", "/").constData(), QByteArray("Basic " + expectedReply).constData()); } void tst_QAuthenticator::ntlmAuth_data() @@ -138,7 +138,7 @@ void tst_QAuthenticator::ntlmAuth() // NTLM phase 2: challenge headers.clear(); - headers << qMakePair(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8()); + headers << qMakePair(QByteArray("WWW-Authenticate"), "NTLM " + data.toUtf8()); priv->parseHttpResponse(headers, /*isProxy = */ false); QEXPECT_FAIL("with-realm", "NTLM authentication code doesn't extract the realm", Continue); diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 2c2b551257..08938be4d1 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -2240,7 +2240,7 @@ void tst_QTcpSocket::suddenRemoteDisconnect() QString::fromLatin1("Could not start %1: %2").arg(processExe, serverProcess.errorString()))); while (!serverProcess.canReadLine()) QVERIFY(serverProcess.waitForReadyRead(10000)); - QCOMPARE(serverProcess.readLine().data(), (server.toLatin1() + "\n").data()); + QCOMPARE(serverProcess.readLine().data(), QByteArray(server.toLatin1() + "\n").data()); // Start client QProcess clientProcess; @@ -2250,7 +2250,7 @@ void tst_QTcpSocket::suddenRemoteDisconnect() QString::fromLatin1("Could not start %1: %2").arg(processExe, clientProcess.errorString()))); while (!clientProcess.canReadLine()) QVERIFY(clientProcess.waitForReadyRead(10000)); - QCOMPARE(clientProcess.readLine().data(), (client.toLatin1() + "\n").data()); + QCOMPARE(clientProcess.readLine().data(), QByteArray(client.toLatin1() + "\n").data()); // Let them play for a while qDebug("Running stress test for 5 seconds"); diff --git a/tests/benchmarks/corelib/tools/containers-associative/main.cpp b/tests/benchmarks/corelib/tools/containers-associative/main.cpp index 7f2e7b68ca..ab1c406708 100644 --- a/tests/benchmarks/corelib/tools/containers-associative/main.cpp +++ b/tests/benchmarks/corelib/tools/containers-associative/main.cpp @@ -72,8 +72,8 @@ void tst_associative_containers::insert_data() const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("hash--" + sizeString).constData()) << true << size; - QTest::newRow(("map--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("hash--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("map--" + sizeString).constData()) << false << size; } } @@ -104,8 +104,8 @@ void tst_associative_containers::lookup_data() const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("hash--" + sizeString).constData()) << true << size; - QTest::newRow(("map--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("hash--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("map--" + sizeString).constData()) << false << size; } } diff --git a/tests/benchmarks/corelib/tools/containers-sequential/main.cpp b/tests/benchmarks/corelib/tools/containers-sequential/main.cpp index e42a40b110..43eadb6633 100644 --- a/tests/benchmarks/corelib/tools/containers-sequential/main.cpp +++ b/tests/benchmarks/corelib/tools/containers-sequential/main.cpp @@ -176,8 +176,8 @@ void tst_vector_vs_std::insert_int_data() for (int size = 10; size < 20000; size += 100) { const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("std::vector-int--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("QVector-int--" + sizeString).constData()) << false << size; } } @@ -199,8 +199,8 @@ void tst_vector_vs_std::insert_Large_data() for (int size = 10; size < LARGE_MAX_SIZE; size += 100) { const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("std::vector-Large--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("QVector-Large--" + sizeString).constData()) << false << size; } } @@ -222,8 +222,8 @@ void tst_vector_vs_std::lookup_int_data() for (int size = 10; size < 20000; size += 100) { const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-int--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-int--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("std::vector-int--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("QVector-int--" + sizeString).constData()) << false << size; } } @@ -245,8 +245,8 @@ void tst_vector_vs_std::lookup_Large_data() for (int size = 10; size < LARGE_MAX_SIZE; size += 100) { const QByteArray sizeString = QByteArray::number(size); - QTest::newRow(("std::vector-Large--" + sizeString).constData()) << true << size; - QTest::newRow(("QVector-Large--" + sizeString).constData()) << false << size; + QTest::newRow(QByteArray("std::vector-Large--" + sizeString).constData()) << true << size; + QTest::newRow(QByteArray("QVector-Large--" + sizeString).constData()) << false << size; } } diff --git a/tests/benchmarks/dbus/qdbustype/main.cpp b/tests/benchmarks/dbus/qdbustype/main.cpp index 0e0ce358bb..b0f6988425 100644 --- a/tests/benchmarks/dbus/qdbustype/main.cpp +++ b/tests/benchmarks/dbus/qdbustype/main.cpp @@ -56,7 +56,7 @@ private Q_SLOTS: static inline void benchmarkAddRow(const char *name, const char *data) { - QTest::newRow(QByteArray("native-") + name) << data << true; + QTest::newRow(QByteArray(QByteArray("native-") + name)) << data << true; QTest::newRow(name) << data << false; } diff --git a/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp b/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp index fcddf5ed90..45acd41749 100644 --- a/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp +++ b/tests/benchmarks/gui/styles/qstylesheetstyle/main.cpp @@ -153,9 +153,9 @@ void tst_qstylesheetstyle::grid_data() QTest::addColumn("N"); for (int n = 5; n <= 25; n += 5) { const QByteArray nString = QByteArray::number(n*n); - QTest::newRow(("simple--" + nString).constData()) << false << false << n; - QTest::newRow(("events--" + nString).constData()) << true << false << n; - QTest::newRow(("show--" + nString).constData()) << true << true << n; + QTest::newRow(QByteArray("simple--" + nString).constData()) << false << false << n; + QTest::newRow(QByteArray("events--" + nString).constData()) << true << false << n; + QTest::newRow(QByteArray("show--" + nString).constData()) << true << true << n; } } -- cgit v1.2.3 From fe092d1a6da74c6473ee4e563498821a1e162955 Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Tue, 28 Feb 2012 10:54:34 +0100 Subject: Add support for _NET_ACTIVE_WINDOW on xcb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a _NET_ACTIVE_WINDOW client message instead of xcb_set_input_focus for activating toplevel windows on xcb. According to the Extended Window Manager Hints the right way to activate a top-level window is using _NET_ACTIVE_WINDOW (when it is supported by the WM). Other approaches like calling xcb_set_input_focus should be avoided when possible, since the WM cannot intercept them. Change-Id: I9be4901f56cbcfb563baf73ccd71ff17a9bdc1d2 Reviewed-by: Uli Schlachter Reviewed-by: Samuel Rødal Reviewed-by: Robin Burchell --- src/plugins/platforms/xcb/qxcbwindow.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 6b7e73d02f..1688fdf92b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1168,10 +1168,31 @@ void QXcbWindow::propagateSizeHints() void QXcbWindow::requestActivateWindow() { - if (m_mapped){ - updateNetWmUserTime(connection()->time()); + if (!m_mapped) + return; + + updateNetWmUserTime(connection()->time()); + + if (window()->isTopLevel() + && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) { + xcb_client_message_event_t event; + + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.window = m_window; + event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW); + event.data.data32[0] = 1; + event.data.data32[1] = connection()->time(); + QWindow *focusWindow = QGuiApplication::focusWindow(); + event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE; + event.data.data32[3] = 0; + event.data.data32[4] = 0; + + Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + } else { Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time())); } + connection()->sync(); } -- cgit v1.2.3 From 5cd56df0f2ac09572a90a07ffa1cda02d5d2d2f8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Mar 2012 10:37:58 +0100 Subject: qmake-test: Fix jom/nmake handling on Windows. The test fails if MAKEFLAGS is set up for jom since the test always uses nmake. Remove MAKEFLAGS from the process environment. Change-Id: Idaed3cc964832b83c282a59fc5257572c520b882 Reviewed-by: Joerg Bornemann Reviewed-by: Sergio Ahumada --- tests/auto/tools/qmake/testcompiler.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/auto/tools/qmake/testcompiler.cpp b/tests/auto/tools/qmake/testcompiler.cpp index 97c640b28f..4e5dc26eac 100644 --- a/tests/auto/tools/qmake/testcompiler.cpp +++ b/tests/auto/tools/qmake/testcompiler.cpp @@ -132,13 +132,34 @@ bool TestCompiler::errorOut() return false; } +// Return the system environment, remove MAKEFLAGS variable in +// case the CI uses jom passing flags incompatible to nmake +// or vice versa. +static inline QStringList systemEnvironment() +{ +#ifdef Q_OS_WIN + static QStringList result; + if (result.isEmpty()) { + foreach (const QString &variable, QProcess::systemEnvironment()) { + if (variable.startsWith(QStringLiteral("MAKEFLAGS="), Qt::CaseInsensitive)) { + qWarning("Removing environment setting '%s'", qPrintable(variable)); + } else { + result.push_back(variable); + } + } + } +#else + static const QStringList result = QProcess::systemEnvironment(); +#endif // ifdef Q_OS_WIN + return result; +} + bool TestCompiler::runCommand( QString cmdline, bool expectFail ) { testOutput_.append("Running command: " + cmdline); QProcess child; - if (!environment_.empty()) - child.setEnvironment(QProcess::systemEnvironment() + environment_); + child.setEnvironment(systemEnvironment() + environment_); child.start(cmdline); if (!child.waitForStarted(-1)) { -- cgit v1.2.3 From e759f62124d5b8c1fd433b53db2445548a3e8893 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 1 Mar 2012 11:59:03 +0100 Subject: Set texture parameters before allocating the texture. Some drivers use this as a hint to decide on weither to preallocate mipmap memory or not. Change-Id: I2fd438a9625b658c7f30fe39a9d63ba5396f9679 Reviewed-by: Kim M. Kalland --- src/gui/opengl/qopenglframebufferobject.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index a523cd2cf1..aa4941706a 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -407,6 +407,12 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi if (samples == 0) { glGenTextures(1, &texture); glBindTexture(target, texture); + + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); if (mipmap) { @@ -421,10 +427,6 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi GL_RGBA, GL_UNSIGNED_BYTE, NULL); } } - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, texture, 0); -- cgit v1.2.3 From 4908cf2a556948599c40681208438e814ba7b83c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Mar 2012 08:33:15 +0100 Subject: QBoolBlocker: make constructor explicit and disable copying Change-Id: If294eff3f84f837ed554c572527d46a89660de9c Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobject_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index fa1aee8173..710aa630d9 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -284,8 +284,9 @@ private: class QBoolBlocker { + Q_DISABLE_COPY(QBoolBlocker) public: - inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;} + explicit inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;} inline ~QBoolBlocker(){block = reset; } private: bool █ -- cgit v1.2.3 From 762a721f7f544f2428111f70f4d388f2d4134a55 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Thu, 23 Feb 2012 15:57:15 +0000 Subject: Fix buffer overrun crash running MSVC2010 win32 Qt on win64 When loading dnsapi.dll as a plugin, we experience crashes because the calling convention is not specified. The default is _cdecl, but __stdcall (via the WINAPI macro) should be used for windows APIs. Mismatched calling convention results in corruption of local variables, probably because the stack pointer is incorrect and SP offsets are used in optimised builds rather than frame pointer offsets. Since the library has been available since Windows 2000, I don't think that we need to load it dynamically. (Unlike the unix version where it isn't part of the LSB) Also checked that the current release of mingw works. Task-number: QTBUG-24227 Change-Id: I37c0a6aa0c133799c2a6dd9391ca1435ba2539ea Reviewed-by: Friedemann Kleint --- src/network/kernel/kernel.pri | 1 + src/network/kernel/qdnslookup_win.cpp | 35 +++-------------------------------- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index adc72bbcbb..a5508af31f 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -29,6 +29,7 @@ unix:SOURCES += kernel/qdnslookup_unix.cpp kernel/qhostinfo_unix.cpp kernel/qnet win32: { HEADERS += kernel/qnetworkinterface_win_p.h SOURCES += kernel/qdnslookup_win.cpp kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp + LIBS += -ldnsapi } integrity:SOURCES += kernel/qdnslookup_unix.cpp kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp index 9b2c088ee2..e7aaf29135 100644 --- a/src/network/kernel/qdnslookup_win.cpp +++ b/src/network/kernel/qdnslookup_win.cpp @@ -44,46 +44,17 @@ #include #include -#include #include #include QT_BEGIN_NAMESPACE -typedef DNS_STATUS (*dns_query_utf8_proto)(PCSTR,WORD,DWORD,PIP4_ARRAY,PDNS_RECORD*,PVOID*); -static dns_query_utf8_proto local_dns_query_utf8 = 0; -typedef void (*dns_record_list_free_proto)(PDNS_RECORD,DNS_FREE_TYPE); -static dns_record_list_free_proto local_dns_record_list_free = 0; - -static void resolveLibrary() -{ - local_dns_query_utf8 = (dns_query_utf8_proto) QSystemLibrary::resolve(QLatin1String("dnsapi"), "DnsQuery_UTF8"); - local_dns_record_list_free = (dns_record_list_free_proto) QSystemLibrary::resolve(QLatin1String("dnsapi"), "DnsRecordListFree"); -} - void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply) { - // Load DnsQuery_UTF8 and DnsRecordListFree on demand. - static volatile bool triedResolve = false; - if (!triedResolve) { - QMutexLocker locker(QMutexPool::globalInstanceGet(&local_dns_query_utf8)); - if (!triedResolve) { - resolveLibrary(); - triedResolve = true; - } - } - - // If DnsQuery_UTF8 or DnsRecordListFree is missing, fail. - if (!local_dns_query_utf8 || !local_dns_record_list_free) { - reply->error = QDnsLookup::ResolverError, - reply->errorString = tr("Resolver functions not found"); - return; - } - // Perform DNS query. - PDNS_RECORD dns_records; - const DNS_STATUS status = local_dns_query_utf8(requestName, requestType, DNS_QUERY_STANDARD, NULL, &dns_records, NULL); + PDNS_RECORD dns_records = 0; + const DNS_STATUS status = DnsQuery_UTF8(requestName, requestType, DNS_QUERY_STANDARD, NULL, &dns_records, NULL); switch (status) { case ERROR_SUCCESS: break; @@ -172,7 +143,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN } } - local_dns_record_list_free(dns_records, DnsFreeRecordList); + DnsRecordListFree(dns_records, DnsFreeRecordList); } QT_END_NAMESPACE -- cgit v1.2.3 From d19d25a68bd92dc6a1b55de0a5c7e0fcce55299b Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 24 Feb 2012 13:07:24 +0000 Subject: Use QSystemError for QDnsLookup windows backend The OS provides the error string in this case. This gives more information to the developer seeing a generic error. Change-Id: Ia03642982f3513ee5a8a9fa98d918e948f8d97a5 Reviewed-by: Miikka Heikkinen Reviewed-by: Thiago Macieira Reviewed-by: Richard J. Moore --- src/network/kernel/qdnslookup_win.cpp | 3 ++- tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp index e7aaf29135..63f4377dfc 100644 --- a/src/network/kernel/qdnslookup_win.cpp +++ b/src/network/kernel/qdnslookup_win.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -76,7 +77,7 @@ void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestN return; default: reply->error = QDnsLookup::InvalidReplyError; - reply->errorString = tr("Invalid reply received"); + reply->errorString = QSystemError(status, QSystemError::NativeError).toString(); return; } diff --git a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp index 3baca3c50b..249ccd3d75 100644 --- a/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp +++ b/tests/auto/network/kernel/qdnslookup/tst_qdnslookup.cpp @@ -139,7 +139,7 @@ void tst_QDnsLookup::lookup() lookup.lookup(); QVERIFY(waitForDone(&lookup)); QVERIFY(lookup.isFinished()); - QCOMPARE(int(lookup.error()), error); + QVERIFY2(int(lookup.error()) == error, qPrintable(lookup.errorString())); if (error == QDnsLookup::NoError) QVERIFY(lookup.errorString().isEmpty()); QCOMPARE(int(lookup.type()), type); -- cgit v1.2.3 From 30974151c159d42d194b5516efc8ca8d7e611f10 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Thu, 23 Feb 2012 08:50:28 +0100 Subject: Cocoa: Implement QPlatformTheme:palette() Causes a new test failure in QGraphicsProxyWidget::updateAndDelete, expand the EXPECT_FAIL to cover that one as well. Change-Id: If9da757206445d17510c4fac82a559de7b8c0563 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/cocoa/cocoa.pro | 2 + src/plugins/platforms/cocoa/qcocoasystemsettings.h | 54 ++++++++ .../platforms/cocoa/qcocoasystemsettings.mm | 145 +++++++++++++++++++++ src/plugins/platforms/cocoa/qcocoatheme.h | 5 + src/plugins/platforms/cocoa/qcocoatheme.mm | 15 ++- .../tst_qgraphicsproxywidget.cpp | 5 +- 6 files changed, 223 insertions(+), 3 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoasystemsettings.h create mode 100644 src/plugins/platforms/cocoa/qcocoasystemsettings.mm diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 45dd3525d5..ce87de2574 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -27,6 +27,7 @@ OBJECTIVE_SOURCES += main.mm \ qcocoafiledialoghelper.mm \ qcocoafontdialoghelper.mm \ qcocoacursor.mm \ + qcocoasystemsettings.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -51,6 +52,7 @@ HEADERS += qcocoaintegration.h \ qcocoafiledialoghelper.h \ qcocoafontdialoghelper.h \ qcocoacursor.h \ + qcocoasystemsettings.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.h b/src/plugins/platforms/cocoa/qcocoasystemsettings.h new file mode 100644 index 0000000000..84a66d7193 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOASYSTEMSETTINGS_H +#define QCOCOASYSTEMSETTINGS_H + +#include +#include + +QT_BEGIN_NAMESPACE + +QPalette * qt_mac_createSystemPalette(); + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm new file mode 100644 index 0000000000..5170c0bc8a --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcocoasystemsettings.h" + +#include +#include + +QColor qt_mac_colorFromCGColor(CGColorRef cgcolor) +{ + QColor pc; + CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor)); + const CGFloat *components = CGColorGetComponents(cgcolor); + if (model == kCGColorSpaceModelRGB) { + pc.setRgbF(components[0], components[1], components[2], components[3]); + } else if (model == kCGColorSpaceModelCMYK) { + pc.setCmykF(components[0], components[1], components[2], components[3]); + } else if (model == kCGColorSpaceModelMonochrome) { + pc.setRgbF(components[0], components[0], components[0], components[1]); + } else { + // Colorspace we can't deal with. + qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model); + Q_ASSERT(false); + } + return pc; +} + +QColor qt_mac_colorForTheme(ThemeBrush brush) +{ + QCFType cgClr = 0; + HIThemeBrushCreateCGColor(brush, &cgClr); + return qt_mac_colorFromCGColor(cgClr); +} + +QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor) +{ + // No GetThemeTextColor in 64-bit mode, use hardcoded values: + switch (themeColor) { + case kThemeTextColorAlertActive: + case kThemeTextColorTabFrontActive: + case kThemeTextColorBevelButtonActive: + case kThemeTextColorListView: + case kThemeTextColorPlacardActive: + case kThemeTextColorPopupButtonActive: + case kThemeTextColorPopupLabelActive: + case kThemeTextColorPushButtonActive: + return Qt::black; + case kThemeTextColorAlertInactive: + case kThemeTextColorDialogInactive: + case kThemeTextColorPlacardInactive: + return QColor(69, 69, 69, 255); + case kThemeTextColorPopupButtonInactive: + case kThemeTextColorPopupLabelInactive: + case kThemeTextColorPushButtonInactive: + case kThemeTextColorTabFrontInactive: + case kThemeTextColorBevelButtonInactive: + return QColor(127, 127, 127, 255); + default: + return QColor(0, 0, 0, 255); // ### TODO: Sample color like Qt 4. + } +} + +QPalette * qt_mac_createSystemPalette() +{ + QColor qc; + + // Standard palette initialization (copied from Qt 4 styles) + QColor background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey + QColor light(background.lighter()); + QColor dark(background.darker()); + QColor mid(Qt::gray); + QPalette *palette = new QPalette(Qt::black, background, light, dark, mid, Qt::black, Qt::white); + + palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark); + palette->setBrush(QPalette::Disabled, QPalette::Text, dark); + palette->setBrush(QPalette::Disabled, QPalette::ButtonText, dark); + palette->setBrush(QPalette::Disabled, QPalette::Base, background); + palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191)); + palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191)); + palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191)); + + // System palette initialization: + palette->setBrush( QPalette::Active, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushPrimaryHighlightColor) ); + palette->setBrush( QPalette::Inactive, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushSecondaryHighlightColor) ); + + palette->setBrush( QPalette::Disabled, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushSecondaryHighlightColor) ); + palette->setBrush( QPalette::Active, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonActiveDarkShadow) ); + + palette->setBrush( QPalette::Inactive, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonInactiveDarkShadow) ); + palette->setBrush( QPalette::Disabled, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonInactiveDarkShadow) ); + + qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogActive); + palette->setColor(QPalette::Active, QPalette::Text, qc); + palette->setColor(QPalette::Active, QPalette::WindowText, qc); + palette->setColor(QPalette::Active, QPalette::HighlightedText, qc); + + qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogInactive); + palette->setColor(QPalette::Inactive, QPalette::Text, qc); + palette->setColor(QPalette::Inactive, QPalette::WindowText, qc); + palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc); + palette->setColor(QPalette::Disabled, QPalette::Text, qc); + palette->setColor(QPalette::Disabled, QPalette::WindowText, qc); + palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc); + palette->setBrush(QPalette::ToolTipBase, QColor(255, 255, 199)); + return palette; +} + diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index a7dc973937..fa235b6be0 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE +class QPalette; class QCocoaTheme : public QPlatformTheme { public: @@ -60,7 +61,11 @@ public: bool usePlatformNativeDialog(DialogType dialogType) const; QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const; + const QPalette *palette(Palette type = SystemPalette) const; + QVariant themeHint(ThemeHint hint) const; +private: + mutable QPalette *m_systemPalette; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 0fef3234b4..6b0e04acf8 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -45,17 +45,19 @@ #include "qcocoacolordialoghelper.h" #include "qcocoafiledialoghelper.h" #include "qcocoafontdialoghelper.h" +#include "qcocoasystemsettings.h" QT_BEGIN_NAMESPACE QCocoaTheme::QCocoaTheme() + :m_systemPalette(0) { } QCocoaTheme::~QCocoaTheme() { - + delete m_systemPalette; } QPlatformMenu *QCocoaTheme::createPlatformMenu(QMenu *menu) const @@ -102,6 +104,17 @@ QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialo } } +const QPalette *QCocoaTheme::palette(Palette type) const +{ + if (type == SystemPalette) { + if (!m_systemPalette) + m_systemPalette = qt_mac_createSystemPalette(); + + return m_systemPalette; + } + return 0; +} + QVariant QCocoaTheme::themeHint(ThemeHint hint) const { switch (hint) { diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index ca5b992012..843b584ce5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -3379,10 +3379,11 @@ void tst_QGraphicsProxyWidget::updateAndDelete() // Update and hide. proxy->update(); proxy->hide(); - QTRY_COMPARE(view.npaints, 1); #ifdef Q_OS_MAC - QEXPECT_FAIL("", "QTBUG-23700", Continue); + QEXPECT_FAIL("", "QTBUG-23700", Abort); #endif + + QTRY_COMPARE(view.npaints, 1); QCOMPARE(view.paintEventRegion, expectedRegion); proxy->show(); -- cgit v1.2.3 From 15c141511fab24233d42b3c8593f0781a4931c8a Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 28 Feb 2012 19:54:46 +0100 Subject: QPair: specialise QTypeInfo based on the typeinfos of its arguments Specialise QTypeInfo> based on the properties of T1 and T2: - If either T1 or T2 is Q_COMPLEX_TYPE, so is QPair. - Otherwise, if either T1 or T2 is Q_MOVABLE_TYPE, so is QPair. - Otherwise, QPair is Q_PRIMITIVE_TYPE. Change-Id: I8aecbd37e3b7924f77f38967498deabf1a19ca24 Reviewed-by: Olivier Goffart Reviewed-by: Thiago Macieira Reviewed-by: Stephen Kelly --- src/corelib/tools/qpair.h | 16 ++++ .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 39 ++++++++ tests/auto/corelib/tools/qpair/qpair.pro | 4 + tests/auto/corelib/tools/qpair/tst_qpair.cpp | 105 +++++++++++++++++++++ tests/auto/corelib/tools/tools.pro | 1 + 5 files changed, 165 insertions(+) create mode 100644 tests/auto/corelib/tools/qpair/qpair.pro create mode 100644 tests/auto/corelib/tools/qpair/tst_qpair.cpp diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 501f2af3e6..29eb58bd22 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -65,6 +65,22 @@ struct QPair T2 second; }; +// mark QPair as complex/movable/primitive depending on the +// typeinfos of the constituents: +template +class QTypeInfo< QPair > +{ +public: + enum { + isComplex = QTypeInfo::isComplex || QTypeInfo::isComplex, + isStatic = QTypeInfo::isStatic || QTypeInfo::isStatic, + isLarge = sizeof(QPair) > sizeof(void*), + isPointer = false, + isDummy = false, + sizeOf = sizeof(QPair) + }; +}; + template Q_INLINE_TEMPLATE bool operator==(const QPair &p1, const QPair &p2) { return p1.first == p2.first && p1.second == p2.second; } diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 72913d10f2..06919c6f58 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -682,6 +682,36 @@ public: }; Q_DECLARE_METATYPE(CustomMultiInheritanceObject*); +class C { char _[4]; }; +class M { char _[4]; }; +class P { char _[4]; }; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(M, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(P, Q_PRIMITIVE_TYPE); +QT_END_NAMESPACE + +// avoid the comma: +typedef QPair QPairCC; +typedef QPair QPairCM; +typedef QPair QPairCP; +typedef QPair QPairMC; +typedef QPair QPairMM; +typedef QPair QPairMP; +typedef QPair QPairPC; +typedef QPair QPairPM; +typedef QPair QPairPP; + +Q_DECLARE_METATYPE(QPairCC) +Q_DECLARE_METATYPE(QPairCM) +Q_DECLARE_METATYPE(QPairCP) +Q_DECLARE_METATYPE(QPairMC) +Q_DECLARE_METATYPE(QPairMM) +Q_DECLARE_METATYPE(QPairMP) +Q_DECLARE_METATYPE(QPairPC) +Q_DECLARE_METATYPE(QPairPM) +Q_DECLARE_METATYPE(QPairPP) + void tst_QMetaType::flags_data() { QTest::addColumn("type"); @@ -700,6 +730,15 @@ QT_FOR_EACH_STATIC_CORE_POINTER(ADD_METATYPE_TEST_ROW) QTest::newRow("CustomMovable") << ::qMetaTypeId() << true << true << false; QTest::newRow("CustomObject*") << ::qMetaTypeId() << true << false << true; QTest::newRow("CustomMultiInheritanceObject*") << ::qMetaTypeId() << true << false << true; + QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << false << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << true << true << false; + QTest::newRow("QPair") << ::qMetaTypeId >() << true << false << false; } void tst_QMetaType::flags() diff --git a/tests/auto/corelib/tools/qpair/qpair.pro b/tests/auto/corelib/tools/qpair/qpair.pro new file mode 100644 index 0000000000..9c7752327e --- /dev/null +++ b/tests/auto/corelib/tools/qpair/qpair.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qpair +QT = core testlib +SOURCES = tst_qpair.cpp diff --git a/tests/auto/corelib/tools/qpair/tst_qpair.cpp b/tests/auto/corelib/tools/qpair/tst_qpair.cpp new file mode 100644 index 0000000000..5de1e8f8bb --- /dev/null +++ b/tests/auto/corelib/tools/qpair/tst_qpair.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +class tst_QPair : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void dummy() {} +}; + +class C { char _[4]; }; +class M { char _[4]; }; +class P { char _[4]; }; + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(M, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(P, Q_PRIMITIVE_TYPE); +QT_END_NAMESPACE + +// avoid the comma: +typedef QPair QPairCC; +typedef QPair QPairCM; +typedef QPair QPairCP; +typedef QPair QPairMC; +typedef QPair QPairMM; +typedef QPair QPairMP; +typedef QPair QPairPC; +typedef QPair QPairPM; +typedef QPair QPairPP; + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT( QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT( QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT( QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT( QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT(!QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT(!QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT( QTypeInfo::isStatic ); + +Q_STATIC_ASSERT( QTypeInfo::isComplex); +Q_STATIC_ASSERT(!QTypeInfo::isStatic ); + +Q_STATIC_ASSERT(!QTypeInfo::isComplex); +Q_STATIC_ASSERT(!QTypeInfo::isStatic ); + +Q_STATIC_ASSERT(!QTypeInfo::isDummy ); +Q_STATIC_ASSERT(!QTypeInfo::isPointer); + + +QTEST_APPLESS_MAIN(tst_QPair) +#include "tst_qpair.moc" diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 930799e3b3..89bb3bc416 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -20,6 +20,7 @@ SUBDIRS=\ qlocale \ qmap \ qmargins \ + qpair \ qpoint \ qqueue \ qrect \ -- cgit v1.2.3 From 6e483e8385a6f1ec4af6b16bb792b272f0389ff4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Mar 2012 15:40:25 +0100 Subject: Windows: Use correct drop data in processDrop(). Fix Qt Designer Drag & Drop. Change-Id: Iabed622efc5e23080f7a91b8d9e433e2c0cee063 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsdrag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 89ca6204a8..d75752bc04 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -658,7 +658,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, QWindowsDrag *windowsDrag = QWindowsDrag::instance(); const QPlatformDropQtResponse response = - QWindowSystemInterface::handleDrop(dropWindow, windowsDrag->platformDropData(), m_lastPoint, + QWindowSystemInterface::handleDrop(dropWindow, windowsDrag->dropData(), m_lastPoint, translateToQDragDropActions(*pdwEffect)); if (response.isAccepted()) { -- cgit v1.2.3 From 10ac80708555cd0cca181e637d3a95c80826ec69 Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Fri, 16 Dec 2011 19:26:40 +0100 Subject: Add support for QRawFont in QTextLayout. The purpose of this change is to allow shaping complex text while using QRawFont. This is needed for WebKit so that we can switch to using QRawFont everywhere and be more in line with what other WebKit ports do. Since this change slightly bends the aim of QRawFont, let's reserve this for internal use for now. Change-Id: I5ec0881f50ce288350bd277570cb5f1fb70c355c Reviewed-by: Simon Hausmann --- src/gui/text/qfontdatabase.h | 1 + src/gui/text/qrawfont.h | 1 + src/gui/text/qtextengine.cpp | 174 +++++++++++++++++++++++++++++-------------- src/gui/text/qtextengine_p.h | 8 +- src/gui/text/qtextlayout.cpp | 44 ++++++++--- src/gui/text/qtextlayout.h | 7 ++ 6 files changed, 171 insertions(+), 64 deletions(-) diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index b30f7da48d..b5697990f8 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -162,6 +162,7 @@ private: friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; friend class QFontEngineMultiQPA; + friend class QTextEngine; #ifdef QT_BUILD_INTERNAL friend class ::tst_QFont; #endif diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 5cd996e705..bc5f6621c8 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -138,6 +138,7 @@ public: private: friend class QRawFontPrivate; friend class QTextLayout; + friend class QTextEngine; QExplicitlySharedDataPointer d; }; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index c63f0fede8..a95e61342d 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -53,6 +53,8 @@ #include "qstring.h" #include #include "qtextdocument_p.h" +#include "qrawfont.h" +#include "qrawfont_p.h" #include #include #include @@ -60,6 +62,8 @@ QT_BEGIN_NAMESPACE +static const float smallCapsFraction = 0.7; + namespace { // Helper class used in QTextEngine::itemize // keep it out here to allow us to keep supporting various compilers. @@ -900,13 +904,25 @@ void QTextEngine::shapeText(int item) const return; QGlyphLayout glyphs = shapedGlyphs(&si); - QFont font = this->font(si); - bool letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute; - QFixed letterSpacing = font.d->letterSpacing; - QFixed wordSpacing = font.d->wordSpacing; + bool letterSpacingIsAbsolute; + QFixed letterSpacing, wordSpacing; +#ifndef QT_NO_RAWFONT + if (useRawFont) { + QTextCharFormat f = format(&si); + wordSpacing = QFixed::fromReal(f.fontWordSpacing()); + letterSpacing = QFixed::fromReal(f.fontLetterSpacing()); + letterSpacingIsAbsolute = true; + } else +#endif + { + QFont font = this->font(si); + letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute; + letterSpacing = font.d->letterSpacing; + wordSpacing = font.d->wordSpacing; - if (letterSpacingIsAbsolute && letterSpacing.value()) - letterSpacing *= font.d->dpi / qt_defaultDpiY(); + if (letterSpacingIsAbsolute && letterSpacing.value()) + letterSpacing *= font.d->dpi / qt_defaultDpiY(); + } if (letterSpacing != 0) { for (int i = 1; i < si.num_glyphs; ++i) { @@ -973,7 +989,14 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); - bool kerningEnabled = this->font(si).d->kerning; + bool kerningEnabled; +#ifndef QT_NO_RAWFONT + if (useRawFont) { + QTextCharFormat f = format(&si); + kerningEnabled = f.fontKerning(); + } else +#endif + kerningEnabled = this->font(si).d->kerning; HB_ShaperItem entire_shaper_item; qMemSet(&entire_shaper_item, 0, sizeof(entire_shaper_item)); @@ -1159,6 +1182,9 @@ static void init(QTextEngine *e) e->underlinePositions = 0; e->specialData = 0; e->stackEngine = false; +#ifndef QT_NO_RAWFONT + e->useRawFont = false; +#endif } QTextEngine::QTextEngine() @@ -1401,7 +1427,21 @@ void QTextEngine::itemize() const ++it; } } else { - itemizer.generate(0, length, static_cast (fnt.d->capital)); +#ifndef QT_NO_RAWFONT + if (useRawFont && specialData) { + int lastIndex = 0; + for (int i = 0; i < specialData->addFormats.size(); ++i) { + const QTextLayout::FormatRange &range = specialData->addFormats.at(i); + if (range.format.fontCapitalization()) { + itemizer.generate(lastIndex, range.start - lastIndex, QFont::MixedCase); + itemizer.generate(range.start, range.length, range.format.fontCapitalization()); + lastIndex = range.start + range.length; + } + } + itemizer.generate(lastIndex, length - lastIndex, QFont::MixedCase); + } else +#endif + itemizer.generate(0, length, static_cast (fnt.d->capital)); } addRequiredBoundaries(); @@ -1663,59 +1703,85 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix int script = si.analysis.script; QFont font = fnt; - if (hasFormats()) { - if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { +#ifndef QT_NO_RAWFONT + if (useRawFont && rawFont.isValid()) { + if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) { engine = feCache.prevFontEngine; - scaledEngine = feCache.prevScaledFontEngine; } else { - QTextCharFormat f = format(&si); - font = f.font(); - - if (block.docHandle() && block.docHandle()->layout()) { - // Make sure we get the right dpi on printers - QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); - if (pdev) - font = QFont(font, pdev); - } else { - font = font.resolve(fnt); - } - engine = font.d->engineForScript(script); - QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); - if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { - if (font.pointSize() != -1) - font.setPointSize((font.pointSize() * 2) / 3); - else - font.setPixelSize((font.pixelSize() * 2) / 3); - scaledEngine = font.d->engineForScript(script); - } + engine = QFontDatabase::findFont(script, /*fontPrivate*/0, rawFont.d->fontEngine->fontDef, true); feCache.prevFontEngine = engine; - if (engine) - engine->ref.ref(); - feCache.prevScaledFontEngine = scaledEngine; - if (scaledEngine) - scaledEngine->ref.ref(); feCache.prevScript = script; - feCache.prevPosition = si.position; - feCache.prevLength = length(&si); + engine->ref.ref(); + if (feCache.prevScaledFontEngine) + releaseCachedFontEngine(feCache.prevScaledFontEngine); } - } else { - if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) - engine = feCache.prevFontEngine; - else { - engine = font.d->engineForScript(script); - feCache.prevFontEngine = engine; - if (engine) - engine->ref.ref(); - feCache.prevScript = script; - feCache.prevPosition = -1; - feCache.prevLength = -1; - feCache.prevScaledFontEngine = 0; + if (si.analysis.flags & QFont::SmallCaps) { + if (feCache.prevScaledFontEngine) { + scaledEngine = feCache.prevScaledFontEngine; + } else { + QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize()); + scaledEngine = QFontDatabase::findFont(script, /*fontPrivate*/0, scEngine->fontDef, true); + scaledEngine->ref.ref(); + feCache.prevScaledFontEngine = scaledEngine; + } + } + } else +#endif + { + if (hasFormats()) { + if (feCache.prevFontEngine && feCache.prevPosition == si.position && feCache.prevLength == length(&si) && feCache.prevScript == script) { + engine = feCache.prevFontEngine; + scaledEngine = feCache.prevScaledFontEngine; + } else { + QTextCharFormat f = format(&si); + font = f.font(); + + if (block.docHandle() && block.docHandle()->layout()) { + // Make sure we get the right dpi on printers + QPaintDevice *pdev = block.docHandle()->layout()->paintDevice(); + if (pdev) + font = QFont(font, pdev); + } else { + font = font.resolve(fnt); + } + engine = font.d->engineForScript(script); + QTextCharFormat::VerticalAlignment valign = f.verticalAlignment(); + if (valign == QTextCharFormat::AlignSuperScript || valign == QTextCharFormat::AlignSubScript) { + if (font.pointSize() != -1) + font.setPointSize((font.pointSize() * 2) / 3); + else + font.setPixelSize((font.pixelSize() * 2) / 3); + scaledEngine = font.d->engineForScript(script); + } + feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); + feCache.prevScaledFontEngine = scaledEngine; + if (scaledEngine) + scaledEngine->ref.ref(); + feCache.prevScript = script; + feCache.prevPosition = si.position; + feCache.prevLength = length(&si); + } + } else { + if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) + engine = feCache.prevFontEngine; + else { + engine = font.d->engineForScript(script); + feCache.prevFontEngine = engine; + if (engine) + engine->ref.ref(); + feCache.prevScript = script; + feCache.prevPosition = -1; + feCache.prevLength = -1; + feCache.prevScaledFontEngine = 0; + } } - } - if (si.analysis.flags == QScriptAnalysis::SmallCaps) { - QFontPrivate *p = font.d->smallCapsFontPrivate(); - scaledEngine = p->engineForScript(script); + if (si.analysis.flags == QScriptAnalysis::SmallCaps) { + QFontPrivate *p = font.d->smallCapsFontPrivate(); + scaledEngine = p->engineForScript(script); + } } if (ascent) { diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index b29f626b68..6f1fd713f1 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -581,7 +581,10 @@ public: mutable FontEngineCache feCache; QString text; - QFont fnt; + mutable QFont fnt; +#ifndef QT_NO_RAWFONT + QRawFont rawFont; +#endif QTextBlock block; QTextOption option; @@ -594,6 +597,9 @@ public: uint stackEngine : 1; uint forceJustification : 1; uint visualMovement : 1; +#ifndef QT_NO_RAWFONT + uint useRawFont : 1; +#endif int *underlinePositions; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 943caea644..d5b05a8957 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -361,6 +361,22 @@ QTextLayout::~QTextLayout() delete d; } +#ifndef QT_NO_RAWFONT +/*! + \internal + Sets a raw font, to be used with QTextLayout::glyphRuns. + Note that this only supports the needs of WebKit. + Use of this function with e.g. QTextLayout::draw will result + in undefined behaviour. +*/ +void QTextLayout::setRawFont(const QRawFont &rawFont) +{ + d->rawFont = rawFont; + d->useRawFont = true; + d->resetFontEngineCache(); +} +#endif + /*! Sets the layout's font to the given \a font. The layout is invalidated and must be laid out again. @@ -370,6 +386,9 @@ QTextLayout::~QTextLayout() void QTextLayout::setFont(const QFont &font) { d->fnt = font; +#ifndef QT_NO_RAWFONT + d->useRawFont = false; +#endif d->resetFontEngineCache(); } @@ -2204,15 +2223,17 @@ QList QTextLine::glyphRuns(int from, int length) const continue; } - QFont font = eng->font(si); - + QFont font; QGlyphRun::GlyphRunFlags flags; - if (font.overline()) - flags |= QGlyphRun::Overline; - if (font.underline()) - flags |= QGlyphRun::Underline; - if (font.strikeOut()) - flags |= QGlyphRun::StrikeOut; + if (!eng->useRawFont) { + font = eng->font(si); + if (font.overline()) + flags |= QGlyphRun::Overline; + if (font.underline()) + flags |= QGlyphRun::Underline; + if (font.strikeOut()) + flags |= QGlyphRun::StrikeOut; + } bool rtl = false; if (si.analysis.bidiLevel % 2) { @@ -2264,7 +2285,8 @@ QList QTextLine::glyphRuns(int from, int length) const iterator.getSelectionBounds(&x, &width); if (glyphLayout.numGlyphs > 0) { - QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script); + QFontEngine *mainFontEngine = eng->fontEngine(si); + if (mainFontEngine->type() == QFontEngine::Multi) { QFontEngineMulti *multiFontEngine = static_cast(mainFontEngine); int end = rtl ? glyphLayout.numGlyphs : 0; @@ -2331,6 +2353,10 @@ QList QTextLine::glyphRuns(int from, int length) const */ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatRange *selection) const { +#ifndef QT_NO_RAWFONT + // Not intended to work with rawfont + Q_ASSERT(!eng->useRawFont); +#endif const QScriptLine &line = eng->lines[index]; QPen pen = p->pen(); diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index a3bc79dc52..2c38973371 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -59,6 +59,9 @@ QT_BEGIN_NAMESPACE class QTextEngine; class QFont; +#ifndef QT_NO_RAWFONT +class QRawFont; +#endif class QRect; class QRegion; class QTextFormat; @@ -114,6 +117,10 @@ public: void setFont(const QFont &f); QFont font() const; +#ifndef QT_NO_RAWFONT + void setRawFont(const QRawFont &rawFont); +#endif + void setText(const QString& string); QString text() const; -- cgit v1.2.3 From cc78f47778de0feda95d7a85440d03ad7dcf40bd Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Mon, 16 Jan 2012 17:40:21 +0100 Subject: Allow using multi fontengine in QTextLayout with QRawFont. This change enables us to instantiate a QFontEngineMulti that takes the raw font's font engine as its primary engine but can use fallback engines based on the platform. Since this can be quite expensive, we defer the query for fallback families' names until it's needed and we cache the resulting multi font engine. Change-Id: I390dbc1cb2fe61d56867f29a03f313eb3eb49dc3 Reviewed-by: Simon Hausmann --- src/gui/text/qfont.cpp | 27 ++++++++----- src/gui/text/qfont_p.h | 5 ++- src/gui/text/qfontdatabase.h | 1 - src/gui/text/qfontengine_p.h | 2 + src/gui/text/qfontengine_qpa.cpp | 85 ++++++++++++++++++++++++++++++++++++---- src/gui/text/qfontengine_qpa_p.h | 5 +++ src/gui/text/qtextengine.cpp | 5 ++- 7 files changed, 108 insertions(+), 22 deletions(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index ee833a06cf..3515c7dc3c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2715,18 +2715,22 @@ QFontEngine *QFontCache::findEngine(const Key &key) EngineCache::Iterator it = engineCache.find(key), end = engineCache.end(); if (it == end) return 0; - // found... update the hitcount and timestamp - it.value().hits++; - it.value().timestamp = ++current_timestamp; + updateHitCountAndTimeStamp(it.value()); + + return it.value().data; +} + +void QFontCache::updateHitCountAndTimeStamp(Engine &value) +{ + value.hits++; + value.timestamp = ++current_timestamp; FC_DEBUG("QFontCache: found font engine\n" " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'", - it.value().data, it.value().timestamp, it.value().hits, - it.value().data->ref.load(), it.value().data->cache_count, - it.value().data->name()); - - return it.value().data; + value.data, value.timestamp, value.hits, + value.data->ref.load(), value.data->cache_count, + value.data->name()); } void QFontCache::removeEngine(QFontEngine *engine) @@ -2743,14 +2747,17 @@ void QFontCache::removeEngine(QFontEngine *engine) } } -void QFontCache::insertEngine(const Key &key, QFontEngine *engine) +void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti) { FC_DEBUG("QFontCache: inserting new engine %p", engine); Engine data(engine); data.timestamp = ++current_timestamp; - engineCache.insert(key, data); + if (insertMulti) + engineCache.insertMulti(key, data); + else + engineCache.insert(key, data); // only increase the cost if this is the first time we insert the engine if (engine->cache_count == 0) diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index d10249201a..06cf787880 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -242,9 +242,10 @@ public: EngineCache engineCache; QFontEngine *findEngine(const Key &key); - void insertEngine(const Key &key, QFontEngine *engine); - void removeEngine(QFontEngine *engine); + void updateHitCountAndTimeStamp(Engine &value); + void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false); + void removeEngine(QFontEngine *engine); private: void increaseCost(uint cost); diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index b5697990f8..b30f7da48d 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -162,7 +162,6 @@ private: friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; friend class QFontEngineMultiQPA; - friend class QTextEngine; #ifdef QT_BUILD_INTERNAL friend class ::tst_QFont; #endif diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 023882d560..fed135ea87 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -85,6 +85,7 @@ struct QGlyphLayout; class Q_GUI_EXPORT QFontEngine : public QObject { + Q_OBJECT public: enum Type { Box, @@ -344,6 +345,7 @@ private: class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine { + Q_OBJECT public: explicit QFontEngineMulti(int engineCount); ~QFontEngineMulti(); diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index 33657367fa..48679824a4 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -46,8 +46,10 @@ #include #include -#include #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -662,6 +664,20 @@ void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks) : QFontEngineMulti(fallbacks.size() + 1), fallbackFamilies(fallbacks), script(_script) + , fallbacksQueried(true) +{ + init(fe); +} + +QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script) + : QFontEngineMulti(2) + , script(_script) + , fallbacksQueried(false) +{ + init(fe); +} + +void QFontEngineMultiQPA::init(QFontEngine *fe) { Q_ASSERT(fe && fe->type() != QFontEngine::Multi); engines[0] = fe; @@ -672,18 +688,73 @@ QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QSt void QFontEngineMultiQPA::loadEngine(int at) { + bool canLoadFallbackEngine = true; + if (!fallbacksQueried) { + // Original FontEngine to restore after the fill. + QFontEngine *fe = engines[0]; + fallbackFamilies = QGuiApplicationPrivate::instance()->platformIntegration()->fontDatabase()->fallbacksForFamily(fe->fontDef.family, QFont::Style(fe->fontDef.style) + , QFont::AnyStyle, QUnicodeTables::Script(script)); + if (fallbackFamilies.size() > 1) { + engines.fill(0, fallbackFamilies.size() + 1); + engines[0] = fe; + } else { + // Turns out we lied about having any fallback at all. + canLoadFallbackEngine = false; + engines[1] = fe; + } + fallbacksQueried = true; + } Q_ASSERT(at < engines.size()); Q_ASSERT(engines.at(at) == 0); - QFontDef request = fontDef; - request.styleStrategy |= QFont::NoFontMerging; - request.family = fallbackFamilies.at(at-1); - engines[at] = QFontDatabase::findFont(script, - /*fontprivate*/0, - request, false); + if (canLoadFallbackEngine) { + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate = */0, + request, /*multi = */false); + } Q_ASSERT(engines[at]); engines[at]->ref.ref(); engines[at]->fontDef = request; } +/* + This is used indirectly by QtWebKit when using QTextLayout::setRawFont + + The purpose of this is to provide the necessary font fallbacks when drawing complex + text. Since QtWebKit ends up repeatedly creating QTextLayout instances and passing them + the same raw font over and over again, we want to cache the corresponding multi font engine + as it may contain fallback font engines already. +*/ +QFontEngine* QFontEngineMultiQPA::createMultiFontEngine(QFontEngine *fe, int script) +{ + QFontEngine *engine = 0; + QFontCache::Key key(fe->fontDef, script, /*multi = */true); + QFontCache *fc = QFontCache::instance(); + // We can't rely on the fontDef (and hence the cache Key) + // alone to distinguish webfonts, since these should not be + // accidentally shared, even if the resulting fontcache key + // is strictly identical. See: + // http://www.w3.org/TR/css3-fonts/#font-face-rule + const bool faceIsLocal = !fe->faceId().filename.isEmpty(); + QFontCache::EngineCache::Iterator it = fc->engineCache.find(key), + end = fc->engineCache.end(); + while (it != end && it.key() == key) { + QFontEngineMulti *cachedEngine = qobject_cast(it.value().data); + if (faceIsLocal || (cachedEngine && fe == cachedEngine->engine(0))) { + engine = cachedEngine; + fc->updateHitCountAndTimeStamp(it.value()); + break; + } + it++; + } + if (!engine) { + engine = new QFontEngineMultiQPA(fe, script); + QFontCache::instance()->insertEngine(key, engine, /* insertMulti */ !faceIsLocal); + } + Q_ASSERT(engine); + return engine; +} + QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h index ed2e071ac2..16991ad2ca 100644 --- a/src/gui/text/qfontengine_qpa_p.h +++ b/src/gui/text/qfontengine_qpa_p.h @@ -249,13 +249,18 @@ public: QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); void loadEngine(int at); + static QFontEngine* createMultiFontEngine(QFontEngine *fe, int script); int fallbackFamilyCount() const { return fallbackFamilies.size(); } QString fallbackFamilyAt(int at) const { return fallbackFamilies.at(at); } private: + QFontEngineMultiQPA(QFontEngine *fe, int script); + void init(QFontEngine *fe); + QStringList fallbackFamilies; int script; + bool fallbacksQueried; }; QT_END_NAMESPACE diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index a95e61342d..0460db14d5 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -59,6 +59,7 @@ #include #include +#include "qfontengine_qpa_p.h" QT_BEGIN_NAMESPACE @@ -1708,7 +1709,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix if (feCache.prevFontEngine && feCache.prevFontEngine->type() == QFontEngine::Multi && feCache.prevScript == script) { engine = feCache.prevFontEngine; } else { - engine = QFontDatabase::findFont(script, /*fontPrivate*/0, rawFont.d->fontEngine->fontDef, true); + engine = QFontEngineMultiQPA::createMultiFontEngine(rawFont.d->fontEngine, script); feCache.prevFontEngine = engine; feCache.prevScript = script; engine->ref.ref(); @@ -1720,7 +1721,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix scaledEngine = feCache.prevScaledFontEngine; } else { QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize()); - scaledEngine = QFontDatabase::findFont(script, /*fontPrivate*/0, scEngine->fontDef, true); + scaledEngine = QFontEngineMultiQPA::createMultiFontEngine(scEngine, script); scaledEngine->ref.ref(); feCache.prevScaledFontEngine = scaledEngine; } -- cgit v1.2.3 From d9649812521e9c67cebb2f9a932e853d5333b2b1 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 24 Feb 2012 01:52:11 -0800 Subject: Remove ARMFPA support and Q_DOUBLE_FORMAT detection Remove the -armfpa option the config.tests/unix/doubleformat* detection. The places where we used QT_ARMFPA and Q_DOUBLE_FORMAT has been removed as well. Rationale: ARM FPA with GCC does not work with EABI. Qt currently does not support compiling without EABI, making ARM FPA an impossibility. It is unknown whether other compilers provide ARM FPA support with EABI. Support for ARM FPA can be re-added in the future should the need arise, but since ARM VFP is available for ARMv5 and up, we should encourage implementors to instead use soft-floats or VFP. Change-Id: I3671aba575118ae3e3e6d769759301c8f2f496f5 Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- config.tests/unix/doubleformat.test | 63 ---------------- .../unix/doubleformat/doubleformattest.cpp | 66 ----------------- .../unix/doubleformat/doubleformattest.pro | 3 - configure | 86 +--------------------- src/corelib/global/qnumeric_p.h | 42 ----------- src/corelib/io/qdatastream.cpp | 69 ----------------- src/corelib/tools/qlocale_tools.cpp | 44 +---------- src/corelib/tools/qlocale_tools_p.h | 4 - tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 4 - tests/auto/corelib/tools/qstring/tst_qstring.cpp | 11 +-- tests/auto/other/compiler/tst_compiler.cpp | 10 --- 11 files changed, 7 insertions(+), 395 deletions(-) delete mode 100755 config.tests/unix/doubleformat.test delete mode 100644 config.tests/unix/doubleformat/doubleformattest.cpp delete mode 100644 config.tests/unix/doubleformat/doubleformattest.pro diff --git a/config.tests/unix/doubleformat.test b/config.tests/unix/doubleformat.test deleted file mode 100755 index 996855372b..0000000000 --- a/config.tests/unix/doubleformat.test +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh - -QMKSPEC=$1 -VERBOSE=$2 -SRCDIR=$3 -OUTDIR=$4 - -# debuggery -[ "$VERBOSE" = "yes" ] && echo "Determining floating point word-order... ($*)" - -# build and run a test program -test -d "$OUTDIR/config.tests/unix/doubleformat" || mkdir -p "$OUTDIR/config.tests/unix/doubleformat" -"$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" "$SRCDIR/config.tests/unix/doubleformat/doubleformattest.pro" -o "$OUTDIR/config.tests/unix/doubleformat/Makefile" >/dev/null 2>&1 -cd "$OUTDIR/config.tests/unix/doubleformat" - -DOUBLEFORMAT="UNKNOWN" -[ "$VERBOSE" = "yes" ] && $MAKE || $MAKE >/dev/null 2>&1 - -if [ -f ./doubleformattest ]; then - : # nop -else - [ "$VERBOSE" = "yes" ] && echo "Unknown floating point format!" - exit 2 -fi - -# LE: strings | grep 0123ABCD0123ABCD -# BE: strings | grep DCBA3210DCBA3210 -# -# LE arm-swapped-dword-order: strings | grep ABCD0123ABCD0123 -# BE arm-swapped-dword-order: strings | grep 3210DCBA3210DCBA (untested) - - -if strings ./doubleformattest | grep "0123ABCD0123ABCD" >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Normal little endian format" - DOUBLEFORMAT="LITTLE" -elif strings ./doubleformattest | grep "ABCD0123ABCD0123" >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Swapped little endian format" - DOUBLEFORMAT="LITTLESWAPPED" -elif strings ./doubleformattest | grep "DCBA3210DCBA3210" >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Normal big endian format" - DOUBLEFORMAT="BIG" -elif strings ./doubleformattest | grep "3210DCBA3210DCBA" >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Swapped big endian format" - DOUBLEFORMAT="BIGSWAPPED" -fi - -# done -if [ "$DOUBLEFORMAT" = "LITTLE" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using little endian." - exit 10 -elif [ "$DOUBLEFORMAT" = "BIG" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using big endian." - exit 11 -elif [ "$DOUBLEFORMAT" = "LITTLESWAPPED" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using swapped little endian." - exit 12 -elif [ "$DOUBLEFORMAT" = "BIGSWAPPED" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using swapped big endian." - exit 13 -else - [ "$VERBOSE" = "yes" ] && echo "Unknown floating point format!" - exit 99 -fi diff --git a/config.tests/unix/doubleformat/doubleformattest.cpp b/config.tests/unix/doubleformat/doubleformattest.cpp deleted file mode 100644 index 1a182c668a..0000000000 --- a/config.tests/unix/doubleformat/doubleformattest.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* - -LE: strings | grep 0123ABCD0123ABCD -BE: strings | grep DCBA3210DCBA3210 - -LE arm-swapped-dword-order: strings | grep ABCD0123ABCD0123 -BE arm-swapped-dword-order: strings | grep 3210DCBA3210DCBA (untested) - -tested on x86, arm-le (gp), aix - -*/ - -#include - -// equals static char c [] = "0123ABCD0123ABCD\0\0\0\0\0\0\0" -static double d [] = { 710524581542275055616.0, 710524581542275055616.0, 0.0 }; - -int main(int argc, char **argv) -{ - // make sure the linker doesn't throw away the arrays - double *d2 = (double *) d; - if (argc > 3) - d[1] += 1; - return d2[0] + d[2] + atof(argv[1]); -} diff --git a/config.tests/unix/doubleformat/doubleformattest.pro b/config.tests/unix/doubleformat/doubleformattest.pro deleted file mode 100644 index 7e51deade5..0000000000 --- a/config.tests/unix/doubleformat/doubleformattest.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES = doubleformattest.cpp -CONFIG -= qt dylib -mac:CONFIG -= app_bundle diff --git a/configure b/configure index c5ce9329c8..cde6dccfa1 100755 --- a/configure +++ b/configure @@ -765,8 +765,6 @@ CFG_NAS=no CFG_ACCESSIBILITY=auto CFG_ENDIAN=auto CFG_HOST_ENDIAN=auto -CFG_DOUBLEFORMAT=auto -CFG_ARMFPA=auto CFG_IWMMXT=no CFG_NEON=auto CFG_CLOCK_GETTIME=auto @@ -961,7 +959,7 @@ while [ "$#" -gt 0 ]; do VAL=no ;; #Qt style yes options - -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-wayland|-nis|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-debug-and-release|-exceptions|-harfbuzz|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-phonon-backend|-audio-backend|-declarative-debug|-javascript-jit|-rpath|-force-pkg-config|-icu|-force-asserts|-testcocoon) + -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-xcb|-wayland|-nis|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-debug-and-release|-exceptions|-harfbuzz|-prefix-install|-silent|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-phonon-backend|-audio-backend|-declarative-debug|-javascript-jit|-rpath|-force-pkg-config|-icu|-force-asserts|-testcocoon) VAR=`echo $1 | sed "s,^-\(.*\),\1,"` VAL=yes ;; @@ -1248,13 +1246,6 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; - armfpa) - if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then - CFG_ARMFPA="$VAL" - else - UNKNOWN_OPT=yes - fi - ;; opengl) if [ "$VAL" = "auto" ] || [ "$VAL" = "desktop" ] || [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || @@ -3204,7 +3195,7 @@ Usage: $relconf [-h] [-prefix ] [-prefix-install] [-bindir ] [-libdir [-iconv] [-no-pch] [-pch] [-no-dbus] [-dbus] [-dbus-linked] [-no-gui] [-no-separate-debug-info] [-no-mmx] [-no-3dnow] [-no-sse] [-no-sse2] [-no-sse3] [-no-ssse3] [-no-sse4.1] [-no-sse4.2] [-no-avx] [-no-neon] - [-qtnamespace ] [-qtlibinfix ] [-separate-debug-info] [-armfpa] + [-qtnamespace ] [-qtlibinfix ] [-separate-debug-info] [-no-phonon-backend] [-phonon-backend] [-no-media-backend] [-media-backend] [-no-audio-backend] [-audio-backend] [-no-javascript-jit] [-javascript-jit] [-no-declarative-debug] [-declarative-debug] @@ -3736,12 +3727,6 @@ if [ "$PLATFORM_QPA" = "yes" ]; then -feature- .. Compile in . The available features are described in src/corelib/global/qfeatures.txt - -armfpa ............. Target platform uses the ARM-FPA floating point format. - -no-armfpa .......... Target platform does not use the ARM-FPA floating point format. - - The floating point format is usually autodetected by configure. Use this - to override the detected value. - -little-endian ...... Target platform is little endian (LSB first). -big-endian ......... Target platform is big endian (MSB first). @@ -5589,51 +5574,6 @@ if [ "$CFG_HOST_ENDIAN" = "auto" ]; then fi fi -if [ "$CFG_ARMFPA" != "auto" ]; then - if [ "$CFG_ARMFPA" = "yes" ]; then - if [ "$CFG_ENDIAN" = "Q_LITTLE_ENDIAN" ]; then - CFG_DOUBLEFORMAT="Q_DOUBLE_LITTLE_SWAPPED" - else - CFG_DOUBLEFORMAT="Q_DOUBLE_BIG_SWAPPED" - fi - else - CFG_DOUBLEFORMAT="normal" - fi -fi - - -if [ "$CFG_DOUBLEFORMAT" = "auto" ]; then - if [ "$PLATFORM_QPA" = "yes" ]; then - CFG_DOUBLEFORMAT=normal - else - "$unixtests/doubleformat.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" - F="$?" - if [ "$F" -eq 10 ] && [ "$CFG_ENDIAN" = "Q_LITTLE_ENDIAN" ]; then - CFG_DOUBLEFORMAT=normal - elif [ "$F" -eq 11 ] && [ "$CFG_ENDIAN" = "Q_BIG_ENDIAN" ]; then - CFG_DOUBLEFORMAT=normal - elif [ "$F" -eq 10 ]; then - CFG_DOUBLEFORMAT="Q_DOUBLE_LITTLE" - elif [ "$F" -eq 11 ]; then - CFG_DOUBLEFORMAT="Q_DOUBLE_BIG" - elif [ "$F" -eq 12 ]; then - CFG_DOUBLEFORMAT="Q_DOUBLE_LITTLE_SWAPPED" - CFG_ARMFPA="yes" - elif [ "$F" -eq 13 ]; then - CFG_DOUBLEFORMAT="Q_DOUBLE_BIG_SWAPPED" - CFG_ARMFPA="yes" - else - echo - echo "The system floating point format could not be detected." - echo "This may cause data to be generated in a wrong format" - echo "Turn on verbose messaging (-v) to see the final report." - # we do not fail on this since this is a new test, and if it fails, - # the old behavior should be correct in most cases - CFG_DOUBLEFORMAT=normal - fi - fi -fi - HAVE_STL=no if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS; then HAVE_STL=yes @@ -6543,28 +6483,6 @@ else fi echo "#endif" >>"$outpath/src/corelib/global/qconfig.h.new" -if [ "$CFG_DOUBLEFORMAT" != "normal" ]; then - cat >>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" - fi -fi - CFG_ARCH_STR=`echo $CFG_ARCH | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` CFG_HOST_ARCH_STR=`echo $CFG_HOST_ARCH | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >>"$outpath/src/corelib/global/qconfig.h.new" < 0xf0; -#else if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { return (ch[0] & 0x7f) == 0x7f && ch[1] > 0xf0; } else { return (ch[7] & 0x7f) == 0x7f && ch[6] > 0xf0; } -#endif } static inline bool qt_is_finite(double d) { uchar *ch = (uchar *)&d; -#ifdef QT_ARMFPA - return (ch[3] & 0x7f) != 0x7f || (ch[2] & 0xf0) != 0xf0; -#else if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { return (ch[0] & 0x7f) != 0x7f || (ch[1] & 0xf0) != 0xf0; } else { return (ch[7] & 0x7f) != 0x7f || (ch[6] & 0xf0) != 0xf0; } -#endif } static inline bool qt_is_inf(float d) diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 7920d881b4..f3fe91427a 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -771,10 +771,6 @@ QDataStream &QDataStream::operator>>(float &f) return *this; } -#if defined(Q_DOUBLE_FORMAT) -#define Q_DF(x) Q_DOUBLE_FORMAT[(x)] - '0' -#endif - /*! \overload @@ -797,7 +793,6 @@ QDataStream &QDataStream::operator>>(double &f) f = 0.0; CHECK_STREAM_PRECOND(*this) -#ifndef Q_DOUBLE_FORMAT if (dev->read((char *)&f, 8) != 8) { f = 0.0; setStatus(ReadPastEnd); @@ -811,39 +806,6 @@ QDataStream &QDataStream::operator>>(double &f) f = x.val1; } } -#else - //non-standard floating point format - union { - double val1; - char val2[8]; - } x; - char *p = x.val2; - char b[8]; - if (dev->read(b, 8) == 8) { - if (noswap) { - *p++ = b[Q_DF(0)]; - *p++ = b[Q_DF(1)]; - *p++ = b[Q_DF(2)]; - *p++ = b[Q_DF(3)]; - *p++ = b[Q_DF(4)]; - *p++ = b[Q_DF(5)]; - *p++ = b[Q_DF(6)]; - *p = b[Q_DF(7)]; - } else { - *p++ = b[Q_DF(7)]; - *p++ = b[Q_DF(6)]; - *p++ = b[Q_DF(5)]; - *p++ = b[Q_DF(4)]; - *p++ = b[Q_DF(3)]; - *p++ = b[Q_DF(2)]; - *p++ = b[Q_DF(1)]; - *p = b[Q_DF(0)]; - } - f = x.val1; - } else { - setStatus(ReadPastEnd); - } -#endif return *this; } @@ -1112,7 +1074,6 @@ QDataStream &QDataStream::operator<<(double f) } CHECK_STREAM_WRITE_PRECOND(*this) -#ifndef Q_DOUBLE_FORMAT if (noswap) { if (dev->write((char *)&f, sizeof(double)) != sizeof(double)) q_status = WriteFailed; @@ -1126,36 +1087,6 @@ QDataStream &QDataStream::operator<<(double f) if (dev->write((char *)&x.val2, sizeof(double)) != sizeof(double)) q_status = WriteFailed; } -#else - union { - double val1; - char val2[8]; - } x; - x.val1 = f; - char *p = x.val2; - char b[8]; - if (noswap) { - b[Q_DF(0)] = *p++; - b[Q_DF(1)] = *p++; - b[Q_DF(2)] = *p++; - b[Q_DF(3)] = *p++; - b[Q_DF(4)] = *p++; - b[Q_DF(5)] = *p++; - b[Q_DF(6)] = *p++; - b[Q_DF(7)] = *p; - } else { - b[Q_DF(7)] = *p++; - b[Q_DF(6)] = *p++; - b[Q_DF(5)] = *p++; - b[Q_DF(4)] = *p++; - b[Q_DF(3)] = *p++; - b[Q_DF(2)] = *p++; - b[Q_DF(1)] = *p++; - b[Q_DF(0)] = *p; - } - if (dev->write(b, 8) != 8) - q_status = WriteFailed; -#endif return *this; } diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp index 31a29d7fe1..2d6b8047a6 100644 --- a/src/corelib/tools/qlocale_tools.cpp +++ b/src/corelib/tools/qlocale_tools.cpp @@ -601,7 +601,7 @@ QT_END_INCLUDE_NAMESPACE #error Exactly one of IEEE_BIG_OR_LITTLE_ENDIAN, VAX, or IBM should be defined. #endif -static inline ULong _getWord0(const NEEDS_VOLATILE double x) +static inline ULong getWord0(const NEEDS_VOLATILE double x) { const NEEDS_VOLATILE uchar *ptr = reinterpret_cast(&x); if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { @@ -611,7 +611,7 @@ static inline ULong _getWord0(const NEEDS_VOLATILE double x) } } -static inline void _setWord0(NEEDS_VOLATILE double *x, ULong l) +static inline void setWord0(NEEDS_VOLATILE double *x, ULong l) { NEEDS_VOLATILE uchar *ptr = reinterpret_cast(x); if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { @@ -627,7 +627,7 @@ static inline void _setWord0(NEEDS_VOLATILE double *x, ULong l) } } -static inline ULong _getWord1(const NEEDS_VOLATILE double x) +static inline ULong getWord1(const NEEDS_VOLATILE double x) { const NEEDS_VOLATILE uchar *ptr = reinterpret_cast(&x); if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { @@ -636,7 +636,7 @@ static inline ULong _getWord1(const NEEDS_VOLATILE double x) return (ptr[3]<<24) + (ptr[2]<<16) + (ptr[1]<<8) + ptr[0]; } } -static inline void _setWord1(NEEDS_VOLATILE double *x, ULong l) +static inline void setWord1(NEEDS_VOLATILE double *x, ULong l) { NEEDS_VOLATILE uchar *ptr = reinterpret_cast(x); if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { @@ -652,42 +652,6 @@ static inline void _setWord1(NEEDS_VOLATILE double *x, ULong l) } } -static inline ULong getWord0(const NEEDS_VOLATILE double x) -{ -#ifdef QT_ARMFPA - return _getWord1(x); -#else - return _getWord0(x); -#endif -} - -static inline void setWord0(NEEDS_VOLATILE double *x, ULong l) -{ -#ifdef QT_ARMFPA - _setWord1(x, l); -#else - _setWord0(x, l); -#endif -} - -static inline ULong getWord1(const NEEDS_VOLATILE double x) -{ -#ifdef QT_ARMFPA - return _getWord0(x); -#else - return _getWord1(x); -#endif -} - -static inline void setWord1(NEEDS_VOLATILE double *x, ULong l) -{ -#ifdef QT_ARMFPA - _setWord0(x, l); -#else - _setWord1(x, l); -#endif -} - static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c) { diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h index 2dc5c03a20..d920d41cb3 100644 --- a/src/corelib/tools/qlocale_tools_p.h +++ b/src/corelib/tools/qlocale_tools_p.h @@ -97,15 +97,11 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential, inline bool isZero(double d) { uchar *ch = (uchar *)&d; -#ifdef QT_ARMFPA - return !(ch[3] & 0x7F || ch[2] || ch[1] || ch[0] || ch[7] || ch[6] || ch[5] || ch[4]); -#else if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { return !(ch[0] & 0x7F || ch[1] || ch[2] || ch[3] || ch[4] || ch[5] || ch[6] || ch[7]); } else { return !(ch[7] & 0x7F || ch[6] || ch[5] || ch[4] || ch[3] || ch[2] || ch[1] || ch[0]); } -#endif } // Removes thousand-group separators in "C" locale. diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 02acb00548..b3b573c64b 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -809,11 +809,7 @@ void tst_QLocale::negativeZero() { double negativeZero( 0.0 ); // Initialise to zero. uchar *ptr = (uchar *)&negativeZero; -#ifdef QT_ARMFPA - ptr[3] = 0x80; -#else ptr[QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 7] = 0x80; -#endif QString s = QString::number(negativeZero); QCOMPARE(s, QString("0")); } diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 7e4f591f47..f007d44262 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -4147,16 +4147,7 @@ void tst_QString::tortureSprintfDouble() # error "Q_BYTE_ORDER not defined" # endif -# ifdef QT_ARMFPA - buff[0] = data->bytes[4]; - buff[1] = data->bytes[5]; - buff[2] = data->bytes[6]; - buff[3] = data->bytes[7]; - buff[4] = data->bytes[0]; - buff[5] = data->bytes[1]; - buff[6] = data->bytes[2]; - buff[7] = data->bytes[3]; -# elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN +# if Q_BYTE_ORDER == Q_LITTLE_ENDIAN for (uint i = 0; i < 8; ++i) buff[i] = data->bytes[i]; # else diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index d72a04c8aa..1f461ba10b 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -525,33 +525,23 @@ void tst_Compiler::privateStaticTemplateMember() const // the second member of the union static const union { unsigned char c[8]; double d; } qt_be_inf_bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } }; static const union { unsigned char c[8]; double d; } qt_le_inf_bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } }; -static const union { unsigned char c[8]; double d; } qt_armfpa_inf_bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } }; static inline double qt_inf() { -#ifdef QT_ARMFPA - return qt_armfpa_inf_bytes.d; -#else return (QSysInfo::ByteOrder == QSysInfo::BigEndian ? qt_be_inf_bytes.d : qt_le_inf_bytes.d); -#endif } #else static const unsigned char qt_be_inf_bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }; static const unsigned char qt_le_inf_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }; -static const unsigned char qt_armfpa_inf_bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 }; static inline double qt_inf() { const uchar *bytes; -#ifdef QT_ARMFPA - bytes = qt_armfpa_inf_bytes; -#else bytes = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? qt_be_inf_bytes : qt_le_inf_bytes); -#endif union { uchar c[8]; double d; } returnValue; memcpy(returnValue.c, bytes, sizeof(returnValue.c)); -- cgit v1.2.3 From 933e35ae7e8548ad27c9e85ebfe95ae3eca26619 Mon Sep 17 00:00:00 2001 From: Jiang Jiang Date: Thu, 1 Mar 2012 14:40:21 +0100 Subject: Revert "Don't render glyph with FT with fetchMetricsOnly" Report https://bugs.webkit.org/show_bug.cgi?id=79561 shows that this commit will cause significant slow down in text handling operations. Though the exact reason is unknown we should revert it first and find out the reason later. This reverts commit 692064bcfd116c2f3a2b30572e511ee68c6a0531. Change-Id: I16a56c3093bdfa2119ab6a6e9049ef2925468e29 Reviewed-by: Simon Hausmann --- src/gui/text/qfontengine_ft.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 14e2dba364..8880eb7cb3 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -877,7 +877,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (err != FT_Err_Ok) qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - if (!set || set->outline_drawing || fetchMetricsOnly) + if ((!set || set->outline_drawing) && fetchMetricsOnly) return 0; FT_GlyphSlot slot = face->glyph; -- cgit v1.2.3 From 2658a5201797dd413f26f97bc22e6366dcba5720 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 28 Feb 2012 10:01:24 +0100 Subject: Fix tst_qregexp with QStringBuilder Change-Id: I1ac2a5c9ea5657ad2916465b77271e3d53c67cde Reviewed-by: Rohan McGovern Reviewed-by: Jason McDonald --- tests/auto/corelib/tools/qregexp/tst_qregexp.cpp | 266 +++++++++++------------ 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp index 2995c18dc9..5470de76ee 100644 --- a/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp +++ b/tests/auto/corelib/tools/qregexp/tst_qregexp.cpp @@ -119,43 +119,43 @@ void tst_QRegExp::indexIn_data() stri.setNum(i); // anchors - QTest::newRow( stri + "anc00" ) << QString("a(?=)z") << QString("az") << 0 << 2 << QStringList(); - QTest::newRow( stri + "anc01" ) << QString("a(?!)z") << QString("az") << -1 << -1 << QStringList(); - QTest::newRow( stri + "anc02" ) << QString("a(?:(?=)|(?=))z") << QString("az") << 0 << 2 + QTest::newRow(qPrintable(stri + "anc00")) << QString("a(?=)z") << QString("az") << 0 << 2 << QStringList(); + QTest::newRow(qPrintable(stri + "anc01")) << QString("a(?!)z") << QString("az") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "anc02")) << QString("a(?:(?=)|(?=))z") << QString("az") << 0 << 2 << QStringList(); - QTest::newRow( stri + "anc03" ) << QString("a(?:(?=)|(?!))z") << QString("az") << 0 << 2 + QTest::newRow(qPrintable(stri + "anc03")) << QString("a(?:(?=)|(?!))z") << QString("az") << 0 << 2 << QStringList(); - QTest::newRow( stri + "anc04" ) << QString("a(?:(?!)|(?=))z") << QString("az") << 0 << 2 + QTest::newRow(qPrintable(stri + "anc04")) << QString("a(?:(?!)|(?=))z") << QString("az") << 0 << 2 << QStringList(); - QTest::newRow( stri + "anc05" ) << QString("a(?:(?!)|(?!))z") << QString("az") << -1 << -1 + QTest::newRow(qPrintable(stri + "anc05")) << QString("a(?:(?!)|(?!))z") << QString("az") << -1 << -1 << QStringList(); - QTest::newRow( stri + "anc06" ) << QString("a(?:(?=)|b)z") << QString("az") << 0 << 2 + QTest::newRow(qPrintable(stri + "anc06")) << QString("a(?:(?=)|b)z") << QString("az") << 0 << 2 << QStringList(); - QTest::newRow( stri + "anc07" ) << QString("a(?:(?=)|b)z") << QString("abz") << 0 << 3 + QTest::newRow(qPrintable(stri + "anc07")) << QString("a(?:(?=)|b)z") << QString("abz") << 0 << 3 << QStringList(); - QTest::newRow( stri + "anc08" ) << QString("a(?:(?!)|b)z") << QString("az") << -1 << -1 + QTest::newRow(qPrintable(stri + "anc08")) << QString("a(?:(?!)|b)z") << QString("az") << -1 << -1 << QStringList(); - QTest::newRow( stri + "anc09" ) << QString("a(?:(?!)|b)z") << QString("abz") << 0 << 3 + QTest::newRow(qPrintable(stri + "anc09")) << QString("a(?:(?!)|b)z") << QString("abz") << 0 << 3 << QStringList(); #if 0 - QTest::newRow( stri + "anc10" ) << QString("a?(?=^b$)") << QString("ab") << 0 << 1 + QTest::newRow(qPrintable(stri + "anc10")) << QString("a?(?=^b$)") << QString("ab") << 0 << 1 << QStringList(); - QTest::newRow( stri + "anc11" ) << QString("a?(?=^b$)") << QString("b") << 0 << 0 + QTest::newRow(qPrintable(stri + "anc11")) << QString("a?(?=^b$)") << QString("b") << 0 << 0 << QStringList(); #endif // back-references - QTest::newRow( stri + "bref00" ) << QString("(a*)(\\1)") << QString("aaaaa") << 0 << 4 + QTest::newRow(qPrintable(stri + "bref00")) << QString("(a*)(\\1)") << QString("aaaaa") << 0 << 4 << QStringList( QStringList() << "aa" << "aa" ); - QTest::newRow( stri + "bref01" ) << QString("<(\\w*)>.+") << QString("blablabla") + QTest::newRow(qPrintable(stri + "bref01")) << QString("<(\\w*)>.+") << QString("blablabla") << 0 << 13 << QStringList( QStringList() << "b" ); - QTest::newRow( stri + "bref02" ) << QString("<(\\w*)>.+") << QString("<>blablabla") + QTest::newRow(qPrintable(stri + "bref02")) << QString("<(\\w*)>.+") << QString("<>blablabla") << 0 << 18 << QStringList( QStringList() << "" ); - QTest::newRow( stri + "bref03" ) << QString("((a*\\2)\\2)") << QString("aaaa") << 0 << 4 + QTest::newRow(qPrintable(stri + "bref03")) << QString("((a*\\2)\\2)") << QString("aaaa") << 0 << 4 << QStringList( QStringList() << QString("aaaa") << "aa" ); - QTest::newRow( stri + "bref04" ) << QString("^(aa+)\\1+$") << QString("aaaaaa") << 0 << 6 + QTest::newRow(qPrintable(stri + "bref04")) << QString("^(aa+)\\1+$") << QString("aaaaaa") << 0 << 6 << QStringList( QStringList() << QString("aa") ); - QTest::newRow( stri + "bref05" ) << QString("^(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)" + QTest::newRow(qPrintable(stri + "bref05")) << QString("^(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)(13)(14)" "\\14\\13\\12\\11\\10\\9\\8\\7\\6\\5\\4\\3\\2\\1") << QString("12345678910111213141413121110987654321") << 0 << 38 << QStringList( QStringList() << "1" << "2" << "3" << "4" << "5" << "6" @@ -163,49 +163,49 @@ void tst_QRegExp::indexIn_data() << "12" << "13" << "14"); // captures - QTest::newRow( stri + "cap00" ) << QString("(a*)") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "cap00")) << QString("(a*)") << QString("") << 0 << 0 << QStringList( QStringList() << QString("") ); - QTest::newRow( stri + "cap01" ) << QString("(a*)") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "cap01")) << QString("(a*)") << QString("aaa") << 0 << 3 << QStringList( QStringList() << "aaa" ); - QTest::newRow( stri + "cap02" ) << QString("(a*)") << QString("baaa") << 0 << 0 + QTest::newRow(qPrintable(stri + "cap02")) << QString("(a*)") << QString("baaa") << 0 << 0 << QStringList( QStringList() << QString("") ); - QTest::newRow( stri + "cap03" ) << QString("(a*)(a*)") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "cap03")) << QString("(a*)(a*)") << QString("aaa") << 0 << 3 << QStringList( QStringList() << QString("aaa") << QString("") ); - QTest::newRow( stri + "cap04" ) << QString("(a*)(b*)") << QString("aaabbb") << 0 << 6 + QTest::newRow(qPrintable(stri + "cap04")) << QString("(a*)(b*)") << QString("aaabbb") << 0 << 6 << QStringList( QStringList() << QString("aaa") << QString("bbb") ); - QTest::newRow( stri + "cap06" ) << QString("(a*)a*") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "cap06")) << QString("(a*)a*") << QString("aaa") << 0 << 3 << QStringList( QStringList() << QString("aaa") ); - QTest::newRow( stri + "cap07" ) << QString("((a*a*)*)") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "cap07")) << QString("((a*a*)*)") << QString("aaa") << 0 << 3 << QStringList( QStringList() << "aaa" << QString("aaa") ); - QTest::newRow( stri + "cap08" ) << QString("(((a)*(b)*)*)") << QString("ababa") << 0 << 5 + QTest::newRow(qPrintable(stri + "cap08")) << QString("(((a)*(b)*)*)") << QString("ababa") << 0 << 5 << QStringList( QStringList() << QString("ababa") << QString("a") << QString("a") << "" ); - QTest::newRow( stri + "cap09" ) << QString("(((a)*(b)*)c)*") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "cap09")) << QString("(((a)*(b)*)c)*") << QString("") << 0 << 0 << QStringList( QStringList() << QString("") << QString("") << QString("") << QString("") ); - QTest::newRow( stri + "cap10" ) << QString("(((a)*(b)*)c)*") << QString("abc") << 0 << 3 + QTest::newRow(qPrintable(stri + "cap10")) << QString("(((a)*(b)*)c)*") << QString("abc") << 0 << 3 << QStringList( QStringList() << "abc" << "ab" << "a" << "b" ); - QTest::newRow( stri + "cap11" ) << QString("(((a)*(b)*)c)*") << QString("abcc") << 0 << 4 + QTest::newRow(qPrintable(stri + "cap11")) << QString("(((a)*(b)*)c)*") << QString("abcc") << 0 << 4 << QStringList( QStringList() << "c" << "" << "" << "" ); - QTest::newRow( stri + "cap12" ) << QString("(((a)*(b)*)c)*") << QString("abcac") << 0 << 5 + QTest::newRow(qPrintable(stri + "cap12")) << QString("(((a)*(b)*)c)*") << QString("abcac") << 0 << 5 << QStringList( QStringList() << "ac" << "a" << "a" << "" ); - QTest::newRow( stri + "cap13" ) << QString("(to|top)?(o|polo)?(gical|o?logical)") + QTest::newRow(qPrintable(stri + "cap13")) << QString("(to|top)?(o|polo)?(gical|o?logical)") << QString("topological") << 0 << 11 << QStringList( QStringList() << "top" << "o" << "logical" ); - QTest::newRow( stri + "cap14" ) << QString("(a)+") << QString("aaaa") << 0 << 4 + QTest::newRow(qPrintable(stri + "cap14")) << QString("(a)+") << QString("aaaa") << 0 << 4 << QStringList( QStringList() << "a" ); // concatenation - QTest::newRow( stri + "cat00" ) << QString("") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "cat01" ) << QString("") << QString("a") << 0 << 0 << QStringList(); - QTest::newRow( stri + "cat02" ) << QString("a") << QString("") << -1 << -1 << QStringList(); - QTest::newRow( stri + "cat03" ) << QString("a") << QString("a") << 0 << 1 << QStringList(); - QTest::newRow( stri + "cat04" ) << QString("a") << QString("b") << -1 << -1 << QStringList(); - QTest::newRow( stri + "cat05" ) << QString("b") << QString("a") << -1 << -1 << QStringList(); - QTest::newRow( stri + "cat06" ) << QString("ab") << QString("ab") << 0 << 2 << QStringList(); - QTest::newRow( stri + "cat07" ) << QString("ab") << QString("ba") << -1 << -1 << QStringList(); - QTest::newRow( stri + "cat08" ) << QString("abab") << QString("abbaababab") << 4 << 4 << QStringList(); + QTest::newRow(qPrintable(stri + "cat00")) << QString("") << QString("") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "cat01")) << QString("") << QString("a") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "cat02")) << QString("a") << QString("") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "cat03")) << QString("a") << QString("a") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "cat04")) << QString("a") << QString("b") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "cat05")) << QString("b") << QString("a") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "cat06")) << QString("ab") << QString("ab") << 0 << 2 << QStringList(); + QTest::newRow(qPrintable(stri + "cat07")) << QString("ab") << QString("ba") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "cat08")) << QString("abab") << QString("abbaababab") << 4 << 4 << QStringList(); indexIn_addMoreRows(stri); } @@ -214,96 +214,96 @@ void tst_QRegExp::indexIn_data() void tst_QRegExp::indexIn_addMoreRows(const QByteArray &stri) { // from Perl Cookbook - QTest::newRow( stri + "cook00" ) << QString("^(m*)(d?c{0,3}|c[dm])(1?x{0,3}|x[lc])(v?i{0,3}|i[vx])$") + QTest::newRow(qPrintable(stri + "cook00")) << QString("^(m*)(d?c{0,3}|c[dm])(1?x{0,3}|x[lc])(v?i{0,3}|i[vx])$") << QString("mmxl") << 0 << 4 << QStringList( QStringList() << "mm" << "" << "xl" << "" ); - QTest::newRow( stri + "cook01" ) << QString("(\\S+)(\\s+)(\\S+)") << QString(" a b") << 1 << 5 + QTest::newRow(qPrintable(stri + "cook01")) << QString("(\\S+)(\\s+)(\\S+)") << QString(" a b") << 1 << 5 << QStringList( QStringList() << "a" << " " << "b" ); - QTest::newRow( stri + "cook02" ) << QString("(\\w+)\\s*=\\s*(.*)\\s*$") << QString(" PATH=. ") << 1 + QTest::newRow(qPrintable(stri + "cook02")) << QString("(\\w+)\\s*=\\s*(.*)\\s*$") << QString(" PATH=. ") << 1 << 7 << QStringList( QStringList() << "PATH" << ". " ); - QTest::newRow( stri + "cook03" ) << QString(".{80,}") + QTest::newRow(qPrintable(stri + "cook03")) << QString(".{80,}") << QString("0000000011111111222222223333333344444444555" "5555566666666777777778888888899999999000000" "00aaaaaaaa") << 0 << 96 << QStringList(); - QTest::newRow( stri + "cook04" ) << QString("(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+)") + QTest::newRow(qPrintable(stri + "cook04")) << QString("(\\d+)/(\\d+)/(\\d+) (\\d+):(\\d+):(\\d+)") << QString("1978/05/24 07:30:00") << 0 << 19 << QStringList( QStringList() << "1978" << "05" << "24" << "07" << "30" << "00" ); - QTest::newRow( stri + "cook05" ) << QString("/usr/bin") << QString("/usr/local/bin:/usr/bin") + QTest::newRow(qPrintable(stri + "cook05")) << QString("/usr/bin") << QString("/usr/local/bin:/usr/bin") << 15 << 8 << QStringList(); - QTest::newRow( stri + "cook06" ) << QString("%([0-9A-Fa-f]{2})") << QString("http://%7f") << 7 << 3 + QTest::newRow(qPrintable(stri + "cook06")) << QString("%([0-9A-Fa-f]{2})") << QString("http://%7f") << 7 << 3 << QStringList( QStringList() << "7f" ); - QTest::newRow( stri + "cook07" ) << QString("/\\*.*\\*/") << QString("i++; /* increment i */") << 5 + QTest::newRow(qPrintable(stri + "cook07")) << QString("/\\*.*\\*/") << QString("i++; /* increment i */") << 5 << 17 << QStringList(); - QTest::newRow( stri + "cook08" ) << QString("^\\s+") << QString(" aaa ") << 0 << 3 + QTest::newRow(qPrintable(stri + "cook08")) << QString("^\\s+") << QString(" aaa ") << 0 << 3 << QStringList(); - QTest::newRow( stri + "cook09" ) << QString("\\s+$") << QString(" aaa ") << 6 << 3 + QTest::newRow(qPrintable(stri + "cook09")) << QString("\\s+$") << QString(" aaa ") << 6 << 3 << QStringList(); - QTest::newRow( stri + "cook10" ) << QString("^.*::") << QString("Box::cat") << 0 << 5 + QTest::newRow(qPrintable(stri + "cook10")) << QString("^.*::") << QString("Box::cat") << 0 << 5 << QStringList(); - QTest::newRow( stri + "cook11" ) << QString("^([01]?\\d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\" + QTest::newRow(qPrintable(stri + "cook11")) << QString("^([01]?\\d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\" "d\\d|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-" "4]\\d|25[0-5])\\.([01]?\\d\\d|2[0-4]\\d|25[" "0-5])$") << QString("255.00.40.30") << 0 << 12 << QStringList( QStringList() << "255" << "00" << "40" << "30" ); - QTest::newRow( stri + "cook12" ) << QString("^.*/") << QString(" /usr/local/bin/moc") << 0 << 16 + QTest::newRow(qPrintable(stri + "cook12")) << QString("^.*/") << QString(" /usr/local/bin/moc") << 0 << 16 << QStringList(); - QTest::newRow( stri + "cook13" ) << QString(":co#(\\d+):") << QString("bla:co#55:") << 3 << 7 + QTest::newRow(qPrintable(stri + "cook13")) << QString(":co#(\\d+):") << QString("bla:co#55:") << 3 << 7 << QStringList( QStringList() << "55" ); - QTest::newRow( stri + "cook14" ) << QString("linux") << QString("alphalinuxinunix") << 5 << 5 + QTest::newRow(qPrintable(stri + "cook14")) << QString("linux") << QString("alphalinuxinunix") << 5 << 5 << QStringList(); - QTest::newRow( stri + "cook15" ) << QString("(\\d+\\.?\\d*|\\.\\d+)") << QString("0.0.5") << 0 << 3 + QTest::newRow(qPrintable(stri + "cook15")) << QString("(\\d+\\.?\\d*|\\.\\d+)") << QString("0.0.5") << 0 << 3 << QStringList( QStringList() << "0.0" ); // mathematical trivia - QTest::newRow( stri + "math00" ) << QString("^(a\\1*)$") << QString("a") << 0 << 1 + QTest::newRow(qPrintable(stri + "math00")) << QString("^(a\\1*)$") << QString("a") << 0 << 1 << QStringList( QStringList() << "a" ); - QTest::newRow( stri + "math01" ) << QString("^(a\\1*)$") << QString("aa") << 0 << 2 + QTest::newRow(qPrintable(stri + "math01")) << QString("^(a\\1*)$") << QString("aa") << 0 << 2 << QStringList( QStringList() << "aa" ); - QTest::newRow( stri + "math02" ) << QString("^(a\\1*)$") << QString("aaa") << -1 << -1 + QTest::newRow(qPrintable(stri + "math02")) << QString("^(a\\1*)$") << QString("aaa") << -1 << -1 << QStringList( QStringList() << QString() ); - QTest::newRow( stri + "math03" ) << QString("^(a\\1*)$") << QString("aaaa") << 0 << 4 + QTest::newRow(qPrintable(stri + "math03")) << QString("^(a\\1*)$") << QString("aaaa") << 0 << 4 << QStringList( QStringList() << "aaaa" ); - QTest::newRow( stri + "math04" ) << QString("^(a\\1*)$") << QString("aaaaa") << -1 << -1 + QTest::newRow(qPrintable(stri + "math04")) << QString("^(a\\1*)$") << QString("aaaaa") << -1 << -1 << QStringList( QStringList() << QString() ); - QTest::newRow( stri + "math05" ) << QString("^(a\\1*)$") << QString("aaaaaa") << -1 << -1 + QTest::newRow(qPrintable(stri + "math05")) << QString("^(a\\1*)$") << QString("aaaaaa") << -1 << -1 << QStringList( QStringList() << QString() ); - QTest::newRow( stri + "math06" ) << QString("^(a\\1*)$") << QString("aaaaaaa") << -1 << -1 + QTest::newRow(qPrintable(stri + "math06")) << QString("^(a\\1*)$") << QString("aaaaaaa") << -1 << -1 << QStringList( QStringList() << QString() ); - QTest::newRow( stri + "math07" ) << QString("^(a\\1*)$") << QString("aaaaaaaa") << 0 << 8 + QTest::newRow(qPrintable(stri + "math07")) << QString("^(a\\1*)$") << QString("aaaaaaaa") << 0 << 8 << QStringList( QStringList() << "aaaaaaaa" ); - QTest::newRow( stri + "math08" ) << QString("^(a\\1*)$") << QString("aaaaaaaaa") << -1 << -1 + QTest::newRow(qPrintable(stri + "math08")) << QString("^(a\\1*)$") << QString("aaaaaaaaa") << -1 << -1 << QStringList( QStringList() << QString() ); - QTest::newRow( stri + "math09" ) << QString("^a(?:a(\\1a))*$") << QString("a") << 0 << 1 + QTest::newRow(qPrintable(stri + "math09")) << QString("^a(?:a(\\1a))*$") << QString("a") << 0 << 1 << QStringList( QStringList() << "" ); - QTest::newRow( stri + "math10" ) << QString("^a(?:a(\\1a))*$") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "math10")) << QString("^a(?:a(\\1a))*$") << QString("aaa") << 0 << 3 << QStringList( QStringList() << "a" ); - QTest::newRow( stri + "math13" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" + QTest::newRow(qPrintable(stri + "math13")) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" "?=a$)))*a$") << QString("aaa") << 0 << 3 << QStringList( QStringList() << "a" << "a" << "" ); - QTest::newRow( stri + "math14" ) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" + QTest::newRow(qPrintable(stri + "math14")) << QString("^(?:((?:^a)?\\2\\3)(\\3\\1|(?=a$))(\\1\\2|(" "?=a$)))*a$") << QString("aaaaa") << 0 << 5 << QStringList( QStringList() << "a" << "a" << "aa" ); - QTest::newRow( stri + "math17" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + QTest::newRow(qPrintable(stri + "math17")) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") << QString("aaa") << 0 << 3 << QStringList( QStringList() << "" << "" << "" << "aaa" << "a" << "aa" ); - QTest::newRow( stri + "math18" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + QTest::newRow(qPrintable(stri + "math18")) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") << QString("aaaaa") << 0 << 5 << QStringList( QStringList() << "aaaaa" << "a" << "aaa" << "" << "" << "" ); - QTest::newRow( stri + "math19" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + QTest::newRow(qPrintable(stri + "math19")) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") << QString("aaaaaaaa") << 0 << 8 << QStringList( QStringList() << "" << "" << "" << "aaaaaaaa" << "a" << "aa" ); - QTest::newRow( stri + "math20" ) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" + QTest::newRow(qPrintable(stri + "math20")) << QString("^(?:(a(?:(\\1\\3)(\\1\\2))*(?:\\1\\3)?)|((?" ":(\\4(?:^a)?\\6)(\\4\\5))*(?:\\4\\6)?))$") << QString("aaaaaaaaa") << -1 << -1 << QStringList( QStringList() << QString() @@ -312,7 +312,7 @@ void tst_QRegExp::indexIn_addMoreRows(const QByteArray &stri) << QString() << QString() << QString() ); - QTest::newRow( stri + "math21" ) << QString("^(aa+)\\1+$") << QString("aaaaaaaaaaaa") << 0 << 12 + QTest::newRow(qPrintable(stri + "math21")) << QString("^(aa+)\\1+$") << QString("aaaaaaaaaaaa") << 0 << 12 << QStringList( QStringList() << "aa" ); static const char * const squareRegExp[] = { @@ -350,129 +350,129 @@ void tst_QRegExp::indexIn_addMoreRows(const QByteArray &stri) } // miscellaneous - QTest::newRow( stri + "misc00" ) << QString(email) + QTest::newRow(qPrintable(stri + "misc00")) << QString(email) << QString("email123@example.com") << 0 << 20 << QStringList(); - QTest::newRow( stri + "misc01" ) << QString("[0-9]*\\.[0-9]+") << QString("pi = 3.14") << 5 << 4 + QTest::newRow(qPrintable(stri + "misc01")) << QString("[0-9]*\\.[0-9]+") << QString("pi = 3.14") << 5 << 4 << QStringList(); // or operator - QTest::newRow( stri + "or00" ) << QString("(?:|b)") << QString("xxx") << 0 << 0 << QStringList(); - QTest::newRow( stri + "or01" ) << QString("(?:|b)") << QString("b") << 0 << 1 << QStringList(); - QTest::newRow( stri + "or02" ) << QString("(?:b|)") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "or03" ) << QString("(?:b|)") << QString("b") << 0 << 1 << QStringList(); - QTest::newRow( stri + "or04" ) << QString("(?:||b||)") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "or05" ) << QString("(?:||b||)") << QString("b") << 0 << 1 << QStringList(); - QTest::newRow( stri + "or06" ) << QString("(?:a|b)") << QString("") << -1 << -1 << QStringList(); - QTest::newRow( stri + "or07" ) << QString("(?:a|b)") << QString("cc") << -1 << -1 << QStringList(); - QTest::newRow( stri + "or08" ) << QString("(?:a|b)") << QString("abc") << 0 << 1 << QStringList(); - QTest::newRow( stri + "or09" ) << QString("(?:a|b)") << QString("cba") << 1 << 1 << QStringList(); - QTest::newRow( stri + "or10" ) << QString("(?:ab|ba)") << QString("aba") << 0 << 2 + QTest::newRow(qPrintable(stri + "or00")) << QString("(?:|b)") << QString("xxx") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "or01")) << QString("(?:|b)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "or02")) << QString("(?:b|)") << QString("") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "or03")) << QString("(?:b|)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "or04")) << QString("(?:||b||)") << QString("") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "or05")) << QString("(?:||b||)") << QString("b") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "or06")) << QString("(?:a|b)") << QString("") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "or07")) << QString("(?:a|b)") << QString("cc") << -1 << -1 << QStringList(); + QTest::newRow(qPrintable(stri + "or08")) << QString("(?:a|b)") << QString("abc") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "or09")) << QString("(?:a|b)") << QString("cba") << 1 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "or10")) << QString("(?:ab|ba)") << QString("aba") << 0 << 2 << QStringList(); - QTest::newRow( stri + "or11" ) << QString("(?:ab|ba)") << QString("bab") << 0 << 2 + QTest::newRow(qPrintable(stri + "or11")) << QString("(?:ab|ba)") << QString("bab") << 0 << 2 << QStringList(); - QTest::newRow( stri + "or12" ) << QString("(?:ab|ba)") << QString("caba") << 1 << 2 + QTest::newRow(qPrintable(stri + "or12")) << QString("(?:ab|ba)") << QString("caba") << 1 << 2 << QStringList(); - QTest::newRow( stri + "or13" ) << QString("(?:ab|ba)") << QString("cbab") << 1 << 2 + QTest::newRow(qPrintable(stri + "or13")) << QString("(?:ab|ba)") << QString("cbab") << 1 << 2 << QStringList(); // quantifiers - QTest::newRow( stri + "qua00" ) << QString("((([a-j])){0,0})") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua00")) << QString("((([a-j])){0,0})") << QString("") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua01" ) << QString("((([a-j])){0,0})") << QString("a") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua01")) << QString("((([a-j])){0,0})") << QString("a") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua02" ) << QString("((([a-j])){0,0})") << QString("xyz") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua02")) << QString("((([a-j])){0,0})") << QString("xyz") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua03" ) << QString("((([a-j]))?)") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua03")) << QString("((([a-j]))?)") << QString("") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua04" ) << QString("((([a-j]))?)") << QString("a") << 0 << 1 + QTest::newRow(qPrintable(stri + "qua04")) << QString("((([a-j]))?)") << QString("a") << 0 << 1 << QStringList( QStringList() << "a" << "a" << "a" ); - QTest::newRow( stri + "qua05" ) << QString("((([a-j]))?)") << QString("x") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua05")) << QString("((([a-j]))?)") << QString("x") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua06" ) << QString("((([a-j]))?)") << QString("ab") << 0 << 1 + QTest::newRow(qPrintable(stri + "qua06")) << QString("((([a-j]))?)") << QString("ab") << 0 << 1 << QStringList( QStringList() << "a" << "a" << "a" ); - QTest::newRow( stri + "qua07" ) << QString("((([a-j]))?)") << QString("xa") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua07")) << QString("((([a-j]))?)") << QString("xa") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua08" ) << QString("((([a-j])){0,3})") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua08")) << QString("((([a-j])){0,3})") << QString("") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua09" ) << QString("((([a-j])){0,3})") << QString("a") << 0 << 1 + QTest::newRow(qPrintable(stri + "qua09")) << QString("((([a-j])){0,3})") << QString("a") << 0 << 1 << QStringList( QStringList() << "a" << "a" << "a" ); - QTest::newRow( stri + "qua10" ) << QString("((([a-j])){0,3})") << QString("abcd") << 0 << 3 + QTest::newRow(qPrintable(stri + "qua10")) << QString("((([a-j])){0,3})") << QString("abcd") << 0 << 3 << QStringList( QStringList() << "abc" << "c" << "c" ); - QTest::newRow( stri + "qua11" ) << QString("((([a-j])){0,3})") << QString("abcde") << 0 << 3 + QTest::newRow(qPrintable(stri + "qua11")) << QString("((([a-j])){0,3})") << QString("abcde") << 0 << 3 << QStringList( QStringList() << "abc" << "c" << "c" ); - QTest::newRow( stri + "qua12" ) << QString("((([a-j])){2,4})") << QString("a") << -1 << -1 + QTest::newRow(qPrintable(stri + "qua12")) << QString("((([a-j])){2,4})") << QString("a") << -1 << -1 << QStringList( QStringList() << QString() << QString() << QString() ); - QTest::newRow( stri + "qua13" ) << QString("((([a-j])){2,4})") << QString("ab") << 0 << 2 + QTest::newRow(qPrintable(stri + "qua13")) << QString("((([a-j])){2,4})") << QString("ab") << 0 << 2 << QStringList( QStringList() << "ab" << "b" << "b" ); - QTest::newRow( stri + "qua14" ) << QString("((([a-j])){2,4})") << QString("abcd") << 0 << 4 + QTest::newRow(qPrintable(stri + "qua14")) << QString("((([a-j])){2,4})") << QString("abcd") << 0 << 4 << QStringList( QStringList() << "abcd" << "d" << "d" ); - QTest::newRow( stri + "qua15" ) << QString("((([a-j])){2,4})") << QString("abcdef") << 0 << 4 + QTest::newRow(qPrintable(stri + "qua15")) << QString("((([a-j])){2,4})") << QString("abcdef") << 0 << 4 << QStringList( QStringList() << "abcd" << "d" << "d" ); - QTest::newRow( stri + "qua16" ) << QString("((([a-j])){2,4})") << QString("xaybcd") << 3 << 3 + QTest::newRow(qPrintable(stri + "qua16")) << QString("((([a-j])){2,4})") << QString("xaybcd") << 3 << 3 << QStringList( QStringList() << "bcd" << "d" << "d" ); - QTest::newRow( stri + "qua17" ) << QString("((([a-j])){0,})") << QString("abcdefgh") << 0 << 8 + QTest::newRow(qPrintable(stri + "qua17")) << QString("((([a-j])){0,})") << QString("abcdefgh") << 0 << 8 << QStringList( QStringList() << "abcdefgh" << "h" << "h" ); - QTest::newRow( stri + "qua18" ) << QString("((([a-j])){,0})") << QString("abcdefgh") << 0 << 0 + QTest::newRow(qPrintable(stri + "qua18")) << QString("((([a-j])){,0})") << QString("abcdefgh") << 0 << 0 << QStringList( QStringList() << "" << "" << "" ); - QTest::newRow( stri + "qua19" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("123332333") << 0 + QTest::newRow(qPrintable(stri + "qua19")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("123332333") << 0 << 9 << QStringList( QStringList() << "123332333" << "2333" << "3" ); - QTest::newRow( stri + "qua20" ) << QString("(1(2(3){3,4}){2,3}){1,2}") + QTest::newRow(qPrintable(stri + "qua20")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333323333233331233332333323333") << 0 << 32 << QStringList( QStringList() << "1233332333323333" << "23333" << "3" ); - QTest::newRow( stri + "qua21" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("") << -1 << -1 + QTest::newRow(qPrintable(stri + "qua21")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("") << -1 << -1 << QStringList( QStringList() << QString() << QString() << QString() ); - QTest::newRow( stri + "qua22" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333") << -1 + QTest::newRow(qPrintable(stri + "qua22")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333") << -1 << -1 << QStringList( QStringList() << QString() << QString() << QString() ); - QTest::newRow( stri + "qua23" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333233") << -1 + QTest::newRow(qPrintable(stri + "qua23")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("12333233") << -1 << -1 << QStringList( QStringList() << QString() << QString() << QString() ); - QTest::newRow( stri + "qua24" ) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("122333") << -1 + QTest::newRow(qPrintable(stri + "qua24")) << QString("(1(2(3){3,4}){2,3}){1,2}") << QString("122333") << -1 << -1 << QStringList( QStringList() << QString() << QString() << QString() ); // star operator - QTest::newRow( stri + "star00" ) << QString("(?:)*") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star01" ) << QString("(?:)*") << QString("abc") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star02" ) << QString("(?:a)*") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star03" ) << QString("(?:a)*") << QString("a") << 0 << 1 << QStringList(); - QTest::newRow( stri + "star04" ) << QString("(?:a)*") << QString("aaa") << 0 << 3 << QStringList(); - QTest::newRow( stri + "star05" ) << QString("(?:a)*") << QString("bbbbaaa") << 0 << 0 + QTest::newRow(qPrintable(stri + "star00")) << QString("(?:)*") << QString("") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "star01")) << QString("(?:)*") << QString("abc") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "star02")) << QString("(?:a)*") << QString("") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "star03")) << QString("(?:a)*") << QString("a") << 0 << 1 << QStringList(); + QTest::newRow(qPrintable(stri + "star04")) << QString("(?:a)*") << QString("aaa") << 0 << 3 << QStringList(); + QTest::newRow(qPrintable(stri + "star05")) << QString("(?:a)*") << QString("bbbbaaa") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star06" ) << QString("(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 0 + QTest::newRow(qPrintable(stri + "star06")) << QString("(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star07" ) << QString("(?:b)*(?:a)*") << QString("") << 0 << 0 + QTest::newRow(qPrintable(stri + "star07")) << QString("(?:b)*(?:a)*") << QString("") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star08" ) << QString("(?:b)*(?:a)*") << QString("a") << 0 << 1 + QTest::newRow(qPrintable(stri + "star08")) << QString("(?:b)*(?:a)*") << QString("a") << 0 << 1 << QStringList(); - QTest::newRow( stri + "star09" ) << QString("(?:b)*(?:a)*") << QString("aaa") << 0 << 3 + QTest::newRow(qPrintable(stri + "star09")) << QString("(?:b)*(?:a)*") << QString("aaa") << 0 << 3 << QStringList(); - QTest::newRow( stri + "star10" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaa") << 0 << 7 + QTest::newRow(qPrintable(stri + "star10")) << QString("(?:b)*(?:a)*") << QString("bbbbaaa") << 0 << 7 << QStringList(); - QTest::newRow( stri + "star11" ) << QString("(?:b)*(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 7 + QTest::newRow(qPrintable(stri + "star11")) << QString("(?:b)*(?:a)*") << QString("bbbbaaabbaaaaa") << 0 << 7 << QStringList(); - QTest::newRow( stri + "star12" ) << QString("(?:a|b)*") << QString("c") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star13" ) << QString("(?:a|b)*") << QString("abac") << 0 << 3 + QTest::newRow(qPrintable(stri + "star12")) << QString("(?:a|b)*") << QString("c") << 0 << 0 << QStringList(); + QTest::newRow(qPrintable(stri + "star13")) << QString("(?:a|b)*") << QString("abac") << 0 << 3 << QStringList(); - QTest::newRow( stri + "star14" ) << QString("(?:a|b|)*") << QString("c") << 0 << 0 + QTest::newRow(qPrintable(stri + "star14")) << QString("(?:a|b|)*") << QString("c") << 0 << 0 << QStringList(); - QTest::newRow( stri + "star15" ) << QString("(?:a|b|)*") << QString("abac") << 0 << 3 + QTest::newRow(qPrintable(stri + "star15")) << QString("(?:a|b|)*") << QString("abac") << 0 << 3 << QStringList(); - QTest::newRow( stri + "star16" ) << QString("(?:ab|ba|b)*") << QString("abbbababbbaaab") << 0 << 11 + QTest::newRow(qPrintable(stri + "star16")) << QString("(?:ab|ba|b)*") << QString("abbbababbbaaab") << 0 << 11 << QStringList(); } -- cgit v1.2.3 From d3eb877951b4fb295e1ddc35e5ee53c782784142 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Mar 2012 10:14:08 +0100 Subject: QInputMethodEvent::Attribute: mark as Q_MOVABLE_TYPE Change-Id: Ifb41afdcf17fa8192f37b4900c59e81d4e0bf60f Reviewed-by: Thiago Macieira --- src/gui/kernel/qevent.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index feee7fa837..d70f6be201 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -464,6 +464,7 @@ private: int replace_length; QString tentativeCommit; }; +Q_DECLARE_TYPEINFO(QInputMethodEvent::Attribute, Q_MOVABLE_TYPE); class Q_GUI_EXPORT QInputMethodQueryEvent : public QEvent { -- cgit v1.2.3 From a1c75534a4bca417204725e77945e53059895726 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 24 Feb 2012 22:27:32 +0100 Subject: QtGlobal: remove qIsDetached() There's not a single in-tree user of this function, and the concept is a broken one in MT programs: By the time qIsDetached() returns, the result can already be different due to another thread taking a copy, or a copy in another thread being destroyed (note that this doesn't require mutex use by the user, since we promise (implicitly, if not explicitly) that you can copy from const objects without holding a lock). QTBUG-10813 talks about a use in QCache::trim(), but 677cf76340f88e0fe51c1f75aa512b6d835414ca removed it, so there's no reason to keep it anymore. Change-Id: I20380c12bdf00ac764b89d84392f0f34727b1971 Reviewed-by: Lars Knoll --- dist/changes-5.0.0 | 2 ++ src/corelib/global/qtypeinfo.h | 4 ---- src/gui/image/qpixmapcache_p.h | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 5a9ce7e6c7..e1f1f07203 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -45,6 +45,8 @@ information about a particular change. in Qt4, so these methods return a bool now. If your code used the undocumented QBool, simply replace it with bool. +- qIsDetached<> has been removed without replacement. + - QMetaType: * QMetaType::construct() has been renamed to QMetaType::create(). * QMetaType::unregisterType() has been removed. diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 815be935f7..1c08bbe1cf 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -49,15 +49,12 @@ QT_BEGIN_NAMESPACE /* QTypeInfo - type trait functionality - qIsDetached - data sharing functionality */ /* The catch-all template. */ -template inline bool qIsDetached(T &) { return true; } - template class QTypeInfo { @@ -188,7 +185,6 @@ QT_BEGIN_NAMESPACE #endif #define Q_DECLARE_SHARED(TYPE) \ -template <> inline bool qIsDetached(TYPE &t) { return t.isDetached(); } \ template <> inline void qSwap(TYPE &value1, TYPE &value2) \ { qSwap(value1.data_ptr(), value2.data_ptr()); } \ Q_DECLARE_SHARED_STL(TYPE) diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h index 6ca109b03f..426a6d9954 100644 --- a/src/gui/image/qpixmapcache_p.h +++ b/src/gui/image/qpixmapcache_p.h @@ -96,8 +96,6 @@ public: QPixmapCache::Key key; }; -inline bool qIsDetached(QPixmapCacheEntry &t) { return t.isDetached(); } - QT_END_NAMESPACE #endif // QPIXMAPCACHE_P_H -- cgit v1.2.3 From 4494ddfec7e4a74ae1192eed25edf8e3ee294755 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 1 Mar 2012 14:34:48 +0100 Subject: make default_pro.prf advertize dynamically created .qmake.cache moving the detection of .qmake.cache to the qmake startup had the side effect that a suddenly popping up cache would not be picked up by nested projects any more. this is not supposed to work in the first place, but the syncqt hack for building against non-installed modules relies on it. until we have cleaned that up properly, we need a way to notify qmake about the appearance of the cache file. Change-Id: I450646b936e3bb2ef2ed3aba05df58e521ccdc61 Reviewed-by: Marius Storm-Olsen --- mkspecs/features/default_pre.prf | 3 +++ qmake/project.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf index 1a56787d15..9e142f172d 100644 --- a/mkspecs/features/default_pre.prf +++ b/mkspecs/features/default_pre.prf @@ -48,4 +48,7 @@ CONFIG = lex yacc warn_on debug uic resources $$CONFIG } unset(QTFWD) unset(PRO_BASENAME) + + # Let qmake know about the unexpectedly appearing cache file. + _QMAKE_CACHE_ = $$QMAKE_SYNCQT_OUTDIR/.qmake.cache } diff --git a/qmake/project.cpp b/qmake/project.cpp index 0e0ac93c5a..48c5540076 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1177,6 +1177,8 @@ QMakeProject::parse(const QString &t, QHash &place, int nu } if(var == "REQUIRES") // special case to get communicated to backends! doProjectCheckReqs(vallist, place); + else if (var == "_QMAKE_CACHE_") + Option::mkfile::cachefile = varlist.isEmpty() ? QString() : varlist.at(0); } return true; } -- cgit v1.2.3 From e51e7b851f6452ed19ae960179963559ab0b78ea Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 22 Feb 2012 10:33:09 +0100 Subject: Take into account input shaping in findRealWindow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In previous commits we took into account bound shaping, but X also supports input shaping, so make sure it's inside both input and bounding shaping to consider the position as inside a window My tests show that when unset Bound Shaping and Input Shaping return the rectangle of the window itself, so we need to be inside both of the rectangle sets to consider the position as a dragabble position for the window Change-Id: I77973e51168d2a6d274d166f29f32e1bc02c32c3 Reviewed-by: Samuel Rødal --- src/plugins/platforms/xcb/README | 4 ++-- src/plugins/platforms/xcb/qxcbdrag.cpp | 40 ++++++++++++++++++++-------------- src/plugins/platforms/xcb/xcb.pro | 2 +- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index ab802ced27..17e8bb53eb 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -1,6 +1,6 @@ Required packages: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 0e3807cd7b..a0736d81f1 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -215,6 +215,26 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0); } +static +bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, int shapeType) +{ + bool interacts = true; + xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL); + if (reply) { + xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply); + if (rectangles) { + interacts = false; + const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply); + for (int i = 0; !interacts && i < nRectangles; ++i) { + interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos); + } + } + free(reply); + } + + return interacts; +} + xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md) { if (w == shapedPixmapWindow()->handle()->winId()) @@ -242,22 +262,10 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md bool isAware = reply && reply->type != XCB_NONE; free(reply); if (isAware) { - xcb_xfixes_region_t region = xcb_generate_id(xcb_connection()); - xcb_xfixes_create_region_from_window(xcb_connection(), region, w, XCB_SHAPE_SK_BOUNDING); - xcb_xfixes_fetch_region_reply_t *reply = xcb_xfixes_fetch_region_reply(xcb_connection(), xcb_xfixes_fetch_region(xcb_connection(), region), NULL); - if (reply) { - xcb_rectangle_t *rectangles = xcb_xfixes_fetch_region_rectangles(reply); - if (rectangles) { - windowContainsMouse = false; - const int nRectangles = xcb_xfixes_fetch_region_rectangles_length(reply); - for (int i = 0; !windowContainsMouse && i < nRectangles; ++i) { - windowContainsMouse = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos); - } - } - free(reply); - } - xcb_xfixes_destroy_region(xcb_connection(), region); - + // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we + // need an && here so that in the case one is set and the other is not we still get the correct result. + windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT) && + windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING); if (windowContainsMouse) return w; } diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index 7bad2b4dad..d220766be0 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -94,7 +94,7 @@ contains(DEFINES, XCB_USE_DRI2) { } } -LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes +LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shape DEFINES += $$QMAKE_DEFINES_XCB LIBS += $$QMAKE_LIBS_XCB -- cgit v1.2.3 From 022ff04a6bb76f18b8b4d0a8bbcb2b21bd771546 Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Fri, 24 Feb 2012 18:05:06 +0100 Subject: Unset _NET_WM_USER_TIME_WINDOW before destroying the window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise metacity was crashing when a QWindow was destroyed immediately after being activated, because metacity was trying to select events (XSelectInput) for the already destroyed m_netWmUserTimeWindow. Task-number: QTBUG-24492 Change-Id: Iedbe7bdd6b26110ca8bec6f33525209ae551ffd5 Reviewed-by: Samuel Rødal --- src/plugins/platforms/xcb/qxcbwindow.cpp | 8 ++++++++ tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1688fdf92b..7777820e93 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -369,6 +369,14 @@ void QXcbWindow::destroy() if (m_syncCounter && m_screen->syncRequestSupported()) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); if (m_window) { + if (m_netWmUserTimeWindow) { + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW)); + // Some window managers, like metacity, do XSelectInput on the _NET_WM_USER_TIME_WINDOW window, + // without trapping BadWindow (which crashes when the user time window is destroyed). + connection()->sync(); + xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow); + m_netWmUserTimeWindow = XCB_NONE; + } connection()->removeWindow(m_window); Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); } diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 90c96b4030..f4556f7e32 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -64,6 +64,8 @@ private slots: void touchCancelWithTouchToMouse(); void orientation(); void close(); + void activateAndClose(); + void initTestCase() { touchDevice = new QTouchDevice; @@ -632,5 +634,16 @@ void tst_QWindow::close() QVERIFY(b.close()); } +void tst_QWindow::activateAndClose() +{ + for (int i = 0; i < 10; ++i) { + QWindow window; + window.show(); + QTest::qWaitForWindowShown(&window); + window.requestActivateWindow(); + QTRY_COMPARE(qGuiApp->focusWindow(), &window); + } +} + #include QTEST_MAIN(tst_QWindow); -- cgit v1.2.3 From d13bedb9d8fb66f58ba901864555bcc9b6e463e0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 15:56:28 +0100 Subject: remove assignment of QMAKE_MOC & QMAKE_UIC from mkspecs there is entirely no point in having it there. Change-Id: Ie2fc1e94495119725131cbd50564648cbb4a7dc8 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- mkspecs/aix-g++-64/qmake.conf | 3 --- mkspecs/aix-g++/qmake.conf | 3 --- mkspecs/aix-xlc-64/qmake.conf | 3 --- mkspecs/aix-xlc/qmake.conf | 3 --- mkspecs/common/linux.conf | 3 --- mkspecs/common/mac.conf | 3 --- mkspecs/cygwin-g++/qmake.conf | 3 --- mkspecs/darwin-g++/qmake.conf | 3 --- mkspecs/freebsd-g++/qmake.conf | 3 --- mkspecs/freebsd-g++34/qmake.conf | 3 --- mkspecs/freebsd-g++40/qmake.conf | 3 --- mkspecs/freebsd-icc/qmake.conf | 3 --- mkspecs/hpux-acc-64/qmake.conf | 3 --- mkspecs/hpux-acc-o64/qmake.conf | 3 --- mkspecs/hpux-acc/qmake.conf | 3 --- mkspecs/hpux-g++-64/qmake.conf | 3 --- mkspecs/hpux-g++/qmake.conf | 3 --- mkspecs/hpuxi-acc-32/qmake.conf | 3 --- mkspecs/hpuxi-acc-64/qmake.conf | 3 --- mkspecs/hpuxi-g++-64/qmake.conf | 3 --- mkspecs/hurd-g++/qmake.conf | 3 --- mkspecs/irix-cc-64/qmake.conf | 3 --- mkspecs/irix-cc/qmake.conf | 3 --- mkspecs/irix-g++-64/qmake.conf | 3 --- mkspecs/irix-g++/qmake.conf | 3 --- mkspecs/linux-cxx/qmake.conf | 3 --- mkspecs/linux-ecc-64/qmake.conf | 3 --- mkspecs/linux-icc/qmake.conf | 3 --- mkspecs/linux-kcc/qmake.conf | 3 --- mkspecs/linux-pgcc/qmake.conf | 3 --- mkspecs/lynxos-g++/qmake.conf | 3 --- mkspecs/macx-xlc/qmake.conf | 3 --- mkspecs/netbsd-g++/qmake.conf | 3 --- mkspecs/openbsd-g++/qmake.conf | 3 --- mkspecs/sco-cc/qmake.conf | 3 --- mkspecs/sco-g++/qmake.conf | 3 --- mkspecs/solaris-cc-64/qmake.conf | 3 --- mkspecs/solaris-cc/qmake.conf | 3 --- mkspecs/solaris-g++-64/qmake.conf | 3 --- mkspecs/solaris-g++/qmake.conf | 3 --- mkspecs/tru64-cxx/qmake.conf | 3 --- mkspecs/tru64-g++/qmake.conf | 3 --- mkspecs/unixware-cc/qmake.conf | 3 --- mkspecs/unixware-g++/qmake.conf | 3 --- mkspecs/unsupported/integrity-ghs/qmake.conf | 3 --- mkspecs/unsupported/linux-host-g++/qmake.conf | 3 --- mkspecs/unsupported/qnx-g++/qmake.conf | 3 --- mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf | 3 --- mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf | 3 --- 49 files changed, 147 deletions(-) diff --git a/mkspecs/aix-g++-64/qmake.conf b/mkspecs/aix-g++-64/qmake.conf index b0179d5603..5a73aeb8c1 100644 --- a/mkspecs/aix-g++-64/qmake.conf +++ b/mkspecs/aix-g++-64/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar -X64 cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib -X64 diff --git a/mkspecs/aix-g++/qmake.conf b/mkspecs/aix-g++/qmake.conf index 2e2e991f54..9ddb1619ab 100644 --- a/mkspecs/aix-g++/qmake.conf +++ b/mkspecs/aix-g++/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/aix-xlc-64/qmake.conf b/mkspecs/aix-xlc-64/qmake.conf index 486b8c6f0f..db5ddc33cd 100644 --- a/mkspecs/aix-xlc-64/qmake.conf +++ b/mkspecs/aix-xlc-64/qmake.conf @@ -66,9 +66,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar -X64 cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib -X64 diff --git a/mkspecs/aix-xlc/qmake.conf b/mkspecs/aix-xlc/qmake.conf index 8655db6d82..ff83a45702 100644 --- a/mkspecs/aix-xlc/qmake.conf +++ b/mkspecs/aix-xlc/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthreads -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index f8f007bada..a809a6b6f9 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -46,9 +46,6 @@ QMAKE_CFLAGS_XCB = QMAKE_LIBS_XCB = QMAKE_DEFINES_XCB = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/common/mac.conf b/mkspecs/common/mac.conf index b22b852013..6ba55325e8 100644 --- a/mkspecs/common/mac.conf +++ b/mkspecs/common/mac.conf @@ -21,9 +21,6 @@ QMAKE_LIBS_OPENGL = -framework OpenGL -framework AGL QMAKE_LIBS_OPENGL_QT = $$QMAKE_LIBS_OPENGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_RANLIB = ranlib -s diff --git a/mkspecs/cygwin-g++/qmake.conf b/mkspecs/cygwin-g++/qmake.conf index c46384fc8b..ece21e226f 100644 --- a/mkspecs/cygwin-g++/qmake.conf +++ b/mkspecs/cygwin-g++/qmake.conf @@ -72,9 +72,6 @@ QMAKE_PREFIX_SHLIB = lib QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf index 84dc764e6b..c059f0cb6f 100644 --- a/mkspecs/darwin-g++/qmake.conf +++ b/mkspecs/darwin-g++/qmake.conf @@ -78,9 +78,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib -s diff --git a/mkspecs/freebsd-g++/qmake.conf b/mkspecs/freebsd-g++/qmake.conf index 9d7c4431d8..f1db098c19 100644 --- a/mkspecs/freebsd-g++/qmake.conf +++ b/mkspecs/freebsd-g++/qmake.conf @@ -32,9 +32,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/freebsd-g++34/qmake.conf b/mkspecs/freebsd-g++34/qmake.conf index 0f52993451..ee597de6c5 100644 --- a/mkspecs/freebsd-g++34/qmake.conf +++ b/mkspecs/freebsd-g++34/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/freebsd-g++40/qmake.conf b/mkspecs/freebsd-g++40/qmake.conf index bf4271126a..331c267b9e 100644 --- a/mkspecs/freebsd-g++40/qmake.conf +++ b/mkspecs/freebsd-g++40/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/freebsd-icc/qmake.conf b/mkspecs/freebsd-icc/qmake.conf index acc8f14b3a..fc7251bcbf 100644 --- a/mkspecs/freebsd-icc/qmake.conf +++ b/mkspecs/freebsd-icc/qmake.conf @@ -90,9 +90,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpux-acc-64/qmake.conf b/mkspecs/hpux-acc-64/qmake.conf index b9aaf5ab24..de0fff1d91 100644 --- a/mkspecs/hpux-acc-64/qmake.conf +++ b/mkspecs/hpux-acc-64/qmake.conf @@ -111,9 +111,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpux-acc-o64/qmake.conf b/mkspecs/hpux-acc-o64/qmake.conf index 389e813dba..5773566b9e 100644 --- a/mkspecs/hpux-acc-o64/qmake.conf +++ b/mkspecs/hpux-acc-o64/qmake.conf @@ -109,9 +109,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpux-acc/qmake.conf b/mkspecs/hpux-acc/qmake.conf index d1b6e5ce56..6bc226c7e2 100644 --- a/mkspecs/hpux-acc/qmake.conf +++ b/mkspecs/hpux-acc/qmake.conf @@ -90,9 +90,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpux-g++-64/qmake.conf b/mkspecs/hpux-g++-64/qmake.conf index f796496c56..1f478ccca4 100644 --- a/mkspecs/hpux-g++-64/qmake.conf +++ b/mkspecs/hpux-g++-64/qmake.conf @@ -73,9 +73,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpux-g++/qmake.conf b/mkspecs/hpux-g++/qmake.conf index e9891e79f1..6685fe1a5e 100644 --- a/mkspecs/hpux-g++/qmake.conf +++ b/mkspecs/hpux-g++/qmake.conf @@ -73,9 +73,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpuxi-acc-32/qmake.conf b/mkspecs/hpuxi-acc-32/qmake.conf index d7e4a0ad34..53d05b7450 100644 --- a/mkspecs/hpuxi-acc-32/qmake.conf +++ b/mkspecs/hpuxi-acc-32/qmake.conf @@ -65,9 +65,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpuxi-acc-64/qmake.conf b/mkspecs/hpuxi-acc-64/qmake.conf index 3ed9b55073..d5d51a9dea 100644 --- a/mkspecs/hpuxi-acc-64/qmake.conf +++ b/mkspecs/hpuxi-acc-64/qmake.conf @@ -108,9 +108,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL -lXt QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hpuxi-g++-64/qmake.conf b/mkspecs/hpuxi-g++-64/qmake.conf index a8f445ca00..9d4daae5c3 100644 --- a/mkspecs/hpuxi-g++-64/qmake.conf +++ b/mkspecs/hpuxi-g++-64/qmake.conf @@ -76,9 +76,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread QMAKE_LIBS_YACC = -ly -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/hurd-g++/qmake.conf b/mkspecs/hurd-g++/qmake.conf index 09a72fa0d7..e7416cd9f6 100644 --- a/mkspecs/hurd-g++/qmake.conf +++ b/mkspecs/hurd-g++/qmake.conf @@ -42,9 +42,6 @@ QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 QMAKE_LIBS_OPENVG = -lOpenVG QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/irix-cc-64/qmake.conf b/mkspecs/irix-cc-64/qmake.conf index ec94824be6..ac5f3b5847 100644 --- a/mkspecs/irix-cc-64/qmake.conf +++ b/mkspecs/irix-cc-64/qmake.conf @@ -98,9 +98,6 @@ QMAKE_LIBS_OPENGL = -lGL -lm QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = CC -ar -o QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/irix-cc/qmake.conf b/mkspecs/irix-cc/qmake.conf index 777da9b5db..eaec795f2a 100644 --- a/mkspecs/irix-cc/qmake.conf +++ b/mkspecs/irix-cc/qmake.conf @@ -98,9 +98,6 @@ QMAKE_LIBS_OPENGL = -lGL -lm QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = CC -ar -o QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/irix-g++-64/qmake.conf b/mkspecs/irix-g++-64/qmake.conf index aa853dedfe..2dcd690c5a 100644 --- a/mkspecs/irix-g++-64/qmake.conf +++ b/mkspecs/irix-g++-64/qmake.conf @@ -71,9 +71,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/irix-g++/qmake.conf b/mkspecs/irix-g++/qmake.conf index 77d47a9ce9..c532a35f6f 100644 --- a/mkspecs/irix-g++/qmake.conf +++ b/mkspecs/irix-g++/qmake.conf @@ -71,9 +71,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/linux-cxx/qmake.conf b/mkspecs/linux-cxx/qmake.conf index 79aa834a90..0bd1193730 100644 --- a/mkspecs/linux-cxx/qmake.conf +++ b/mkspecs/linux-cxx/qmake.conf @@ -63,9 +63,6 @@ QMAKE_LIBS_NIS = -lnsl QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_RANLIB = diff --git a/mkspecs/linux-ecc-64/qmake.conf b/mkspecs/linux-ecc-64/qmake.conf index 50f841f1d4..a4b9e03f2c 100644 --- a/mkspecs/linux-ecc-64/qmake.conf +++ b/mkspecs/linux-ecc-64/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf index 4ff63cda71..49a3306538 100644 --- a/mkspecs/linux-icc/qmake.conf +++ b/mkspecs/linux-icc/qmake.conf @@ -74,9 +74,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = xiar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/linux-kcc/qmake.conf b/mkspecs/linux-kcc/qmake.conf index 23fd6298ac..ab1847f42d 100644 --- a/mkspecs/linux-kcc/qmake.conf +++ b/mkspecs/linux-kcc/qmake.conf @@ -76,9 +76,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/linux-pgcc/qmake.conf b/mkspecs/linux-pgcc/qmake.conf index ed88215609..80b4cc28ba 100644 --- a/mkspecs/linux-pgcc/qmake.conf +++ b/mkspecs/linux-pgcc/qmake.conf @@ -67,9 +67,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/lynxos-g++/qmake.conf b/mkspecs/lynxos-g++/qmake.conf index 6b6f4057bf..500dc498ee 100644 --- a/mkspecs/lynxos-g++/qmake.conf +++ b/mkspecs/lynxos-g++/qmake.conf @@ -70,9 +70,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/macx-xlc/qmake.conf b/mkspecs/macx-xlc/qmake.conf index f84524bbdf..77c300a4ae 100644 --- a/mkspecs/macx-xlc/qmake.conf +++ b/mkspecs/macx-xlc/qmake.conf @@ -77,9 +77,6 @@ QMAKE_LIBS_OPENGL = -framework OpenGL -framework AGL QMAKE_LIBS_OPENGL_QT = $$QMAKE_LIBS_OPENGL #QMAKE_LIBS_THREAD = -lpthreads -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib -s diff --git a/mkspecs/netbsd-g++/qmake.conf b/mkspecs/netbsd-g++/qmake.conf index ab4b7c374c..17609f2fb7 100644 --- a/mkspecs/netbsd-g++/qmake.conf +++ b/mkspecs/netbsd-g++/qmake.conf @@ -68,9 +68,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib diff --git a/mkspecs/openbsd-g++/qmake.conf b/mkspecs/openbsd-g++/qmake.conf index 56d94160e3..1539c46960 100644 --- a/mkspecs/openbsd-g++/qmake.conf +++ b/mkspecs/openbsd-g++/qmake.conf @@ -69,9 +69,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar q QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = ranlib diff --git a/mkspecs/sco-cc/qmake.conf b/mkspecs/sco-cc/qmake.conf index 179b774e03..4cb71db520 100644 --- a/mkspecs/sco-cc/qmake.conf +++ b/mkspecs/sco-cc/qmake.conf @@ -63,9 +63,6 @@ QMAKE_LIBS_X11SM = -lSM -lICE QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/sco-g++/qmake.conf b/mkspecs/sco-g++/qmake.conf index 9b321a486a..b4839eb571 100644 --- a/mkspecs/sco-g++/qmake.conf +++ b/mkspecs/sco-g++/qmake.conf @@ -64,9 +64,6 @@ QMAKE_LIBS_X11 = -lXext -lX11 -lsocket -lm QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/solaris-cc-64/qmake.conf b/mkspecs/solaris-cc-64/qmake.conf index 80709af5f4..b28c4505c9 100644 --- a/mkspecs/solaris-cc-64/qmake.conf +++ b/mkspecs/solaris-cc-64/qmake.conf @@ -88,9 +88,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = CC -xar -o QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/solaris-cc/qmake.conf b/mkspecs/solaris-cc/qmake.conf index 0672841acc..e29d37bc87 100644 --- a/mkspecs/solaris-cc/qmake.conf +++ b/mkspecs/solaris-cc/qmake.conf @@ -71,9 +71,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = CC -xar -o QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/solaris-g++-64/qmake.conf b/mkspecs/solaris-g++-64/qmake.conf index 7bc7b9fd60..c08212765d 100644 --- a/mkspecs/solaris-g++-64/qmake.conf +++ b/mkspecs/solaris-g++-64/qmake.conf @@ -92,9 +92,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/solaris-g++/qmake.conf b/mkspecs/solaris-g++/qmake.conf index be21cdd1da..5c9909210f 100644 --- a/mkspecs/solaris-g++/qmake.conf +++ b/mkspecs/solaris-g++/qmake.conf @@ -75,9 +75,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lrt QMAKE_LIBS_NETWORK = -lresolv -lsocket -lxnet -lnsl -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/tru64-cxx/qmake.conf b/mkspecs/tru64-cxx/qmake.conf index afabf3e220..a8db2a3c3a 100644 --- a/mkspecs/tru64-cxx/qmake.conf +++ b/mkspecs/tru64-cxx/qmake.conf @@ -64,9 +64,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lrt -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/tru64-g++/qmake.conf b/mkspecs/tru64-g++/qmake.conf index 6acd5cdb22..e1236cf5f8 100644 --- a/mkspecs/tru64-g++/qmake.conf +++ b/mkspecs/tru64-g++/qmake.conf @@ -66,9 +66,6 @@ QMAKE_LIBS_OPENGL = -lGL QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lpthread -lexc -lrt -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/unixware-cc/qmake.conf b/mkspecs/unixware-cc/qmake.conf index 74478d66e2..4e55970aa7 100644 --- a/mkspecs/unixware-cc/qmake.conf +++ b/mkspecs/unixware-cc/qmake.conf @@ -69,9 +69,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/unixware-g++/qmake.conf b/mkspecs/unixware-g++/qmake.conf index a158d9522a..753c3a86a7 100644 --- a/mkspecs/unixware-g++/qmake.conf +++ b/mkspecs/unixware-g++/qmake.conf @@ -68,9 +68,6 @@ QMAKE_LIBS_OPENGL = -lGL -lXt QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = -lthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cq QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/unsupported/integrity-ghs/qmake.conf b/mkspecs/unsupported/integrity-ghs/qmake.conf index 54253edc8f..7f2ac2fb04 100644 --- a/mkspecs/unsupported/integrity-ghs/qmake.conf +++ b/mkspecs/unsupported/integrity-ghs/qmake.conf @@ -50,9 +50,6 @@ QMAKE_LIBS_X11 = QMAKE_LIBS_X11SM = QMAKE_LIBS_THREAD = -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_RANLIB = diff --git a/mkspecs/unsupported/linux-host-g++/qmake.conf b/mkspecs/unsupported/linux-host-g++/qmake.conf index 1ad529ebae..2e0b7dba44 100644 --- a/mkspecs/unsupported/linux-host-g++/qmake.conf +++ b/mkspecs/unsupported/linux-host-g++/qmake.conf @@ -108,9 +108,6 @@ QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 QMAKE_LIBS_OPENVG = -lOpenVG QMAKE_LIBS_THREAD = -lpthread -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = host-ar cqs QMAKE_OBJCOPY = host-objcopy QMAKE_RANLIB = diff --git a/mkspecs/unsupported/qnx-g++/qmake.conf b/mkspecs/unsupported/qnx-g++/qmake.conf index 83c4a26e06..bc96c21e9f 100644 --- a/mkspecs/unsupported/qnx-g++/qmake.conf +++ b/mkspecs/unsupported/qnx-g++/qmake.conf @@ -37,9 +37,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = -lsocket -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_RANLIB = diff --git a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf index a3b571b144..10f2627d66 100644 --- a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf @@ -84,9 +84,6 @@ QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = # -lnetwrap # only needed if kernel is missing gethostbyname and friends -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = diff --git a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf index 8bdf1c5011..c3c974e3e7 100644 --- a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf @@ -83,9 +83,6 @@ QMAKE_LIBS_OPENGL_QT = -lGL QMAKE_LIBS_THREAD = QMAKE_LIBS_NETWORK = # -lnet # only needed if kernel is missing gethostbyname and friends -QMAKE_MOC = $$[QT_INSTALL_BINS]/moc -QMAKE_UIC = $$[QT_INSTALL_BINS]/uic - QMAKE_AR = ar cqs QMAKE_OBJCOPY = objcopy QMAKE_RANLIB = -- cgit v1.2.3 From 8c7aa37aa7d34860a9c062808416cef0118b36d6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 17:12:32 +0100 Subject: dispose of BOOTSTRAPPING define this is used only in qmake, not in other bootstrapped tools Change-Id: Ie2841e69dbd82c86d2297ddf51443ee75760766c Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qlibraryinfo.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ac99b80cb0..ff1fd6bfdd 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -46,11 +46,7 @@ #include "qlibraryinfo.h" #include "qscopedpointer.h" -#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED) -# define BOOTSTRAPPING -#endif - -#ifdef BOOTSTRAPPING +#ifdef QT_BUILD_QMAKE QT_BEGIN_NAMESPACE extern QString qmake_libraryInfoFile(); QT_END_NAMESPACE @@ -97,7 +93,7 @@ public: QLibrarySettings::QLibrarySettings() : settings(QLibraryInfoPrivate::findConfiguration()) { -#ifndef BOOTSTRAPPING +#ifndef QT_BUILD_QMAKE qAddPostRoutine(QLibraryInfoPrivate::cleanup); #endif } @@ -105,7 +101,7 @@ QLibrarySettings::QLibrarySettings() QSettings *QLibraryInfoPrivate::findConfiguration() { QString qtconfig = QLatin1String(":/qt/etc/qt.conf"); -#ifdef BOOTSTRAPPING +#ifdef QT_BUILD_QMAKE if(!QFile::exists(qtconfig)) qtconfig = qmake_libraryInfoFile(); #else @@ -286,7 +282,7 @@ QLibraryInfo::location(LibraryLocation loc) QString baseDir; if (loc == PrefixPath) { // we make the prefix path absolute to the executable's directory -#ifdef BOOTSTRAPPING +#ifdef QT_BUILD_QMAKE baseDir = QFileInfo(qmake_libraryInfoFile()).absolutePath(); #else if (QCoreApplication::instance()) { -- cgit v1.2.3 From 6663b5ebac7f750a3fb53dc61fbfb466bebec931 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 17:26:59 +0100 Subject: exclude some code from the qmake build Change-Id: Ic989a2cc5106496a2c5f13c863a0a87d5cd2d963 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qlibraryinfo.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index ff1fd6bfdd..c7f0cd1c28 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -148,6 +148,8 @@ QSettings *QLibraryInfoPrivate::findConfiguration() \sa QSysInfo, {Using qt.conf} */ +#ifndef QT_BUILD_QMAKE + /*! \internal You cannot create a QLibraryInfo, instead only the static functions are available to query @@ -210,6 +212,8 @@ QLibraryInfo::isDebugBuild() return false; } +#endif // QT_BUILD_QMAKE + static const struct { char key[14], value[13]; } qtConfEntries[] = { -- cgit v1.2.3 From c0e9041b6dc2cc46334df2dffe640f1ead1e0898 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 14:02:48 +0100 Subject: optimize QMakeProperty make it table-driven and have it cache the immutable values from QLibraryInfo. Change-Id: I07ed89152aa964bc9edf4436ee7c42f99cc6bcd3 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/property.cpp | 66 ++++++++++++++++++++++-------------------------------- qmake/property.h | 4 ++++ 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/qmake/property.cpp b/qmake/property.cpp index 4221605545..dec204cb9c 100644 --- a/qmake/property.cpp +++ b/qmake/property.cpp @@ -51,8 +51,30 @@ QT_BEGIN_NAMESPACE QStringList qmake_mkspec_paths(); //project.cpp +static const struct { + const char *name; + QLibraryInfo::LibraryLocation loc; +} propList[] = { + { "QT_INSTALL_PREFIX", QLibraryInfo::PrefixPath }, + { "QT_INSTALL_DATA", QLibraryInfo::DataPath }, + { "QT_INSTALL_DOCS", QLibraryInfo::DocumentationPath }, + { "QT_INSTALL_HEADERS", QLibraryInfo::HeadersPath }, + { "QT_INSTALL_LIBS", QLibraryInfo::LibrariesPath }, + { "QT_INSTALL_BINS", QLibraryInfo::BinariesPath }, + { "QT_INSTALL_TESTS", QLibraryInfo::TestsPath }, + { "QT_INSTALL_PLUGINS", QLibraryInfo::PluginsPath }, + { "QT_INSTALL_IMPORTS", QLibraryInfo::ImportsPath }, + { "QT_INSTALL_TRANSLATIONS", QLibraryInfo::TranslationsPath }, + { "QT_INSTALL_CONFIGURATION", QLibraryInfo::SettingsPath }, + { "QT_INSTALL_EXAMPLES", QLibraryInfo::ExamplesPath }, + { "QT_INSTALL_DEMOS", QLibraryInfo::ExamplesPath }, // Just backwards compat +}; + QMakeProperty::QMakeProperty() : settings(0) { + for (int i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) + m_values[QString::fromLatin1(propList[i].name)] = + QLibraryInfo::location(propList[i].loc); } QMakeProperty::~QMakeProperty() @@ -80,32 +102,9 @@ QMakeProperty::keyBase(bool version) const QString QMakeProperty::value(QString v, bool just_check) { - if(v == "QT_INSTALL_PREFIX") - return QLibraryInfo::location(QLibraryInfo::PrefixPath); - else if(v == "QT_INSTALL_DATA") - return QLibraryInfo::location(QLibraryInfo::DataPath); - else if(v == "QT_INSTALL_DOCS") - return QLibraryInfo::location(QLibraryInfo::DocumentationPath); - else if(v == "QT_INSTALL_HEADERS") - return QLibraryInfo::location(QLibraryInfo::HeadersPath); - else if(v == "QT_INSTALL_LIBS") - return QLibraryInfo::location(QLibraryInfo::LibrariesPath); - else if(v == "QT_INSTALL_BINS") - return QLibraryInfo::location(QLibraryInfo::BinariesPath); - else if(v == "QT_INSTALL_TESTS") - return QLibraryInfo::location(QLibraryInfo::TestsPath); - else if(v == "QT_INSTALL_PLUGINS") - return QLibraryInfo::location(QLibraryInfo::PluginsPath); - else if(v == "QT_INSTALL_IMPORTS") - return QLibraryInfo::location(QLibraryInfo::ImportsPath); - else if(v == "QT_INSTALL_TRANSLATIONS") - return QLibraryInfo::location(QLibraryInfo::TranslationsPath); - else if(v == "QT_INSTALL_CONFIGURATION") - return QLibraryInfo::location(QLibraryInfo::SettingsPath); - else if(v == "QT_INSTALL_EXAMPLES") - return QLibraryInfo::location(QLibraryInfo::ExamplesPath); - else if(v == "QT_INSTALL_DEMOS") - return QLibraryInfo::location(QLibraryInfo::ExamplesPath); + QString val = m_values.value(v); + if (!val.isNull()) + return val; else if(v == "QMAKE_MKSPECS") return qmake_mkspec_paths().join(Option::dirlist_sep); else if(v == "QMAKE_VERSION") @@ -194,19 +193,8 @@ QMakeProperty::exec() } } QStringList specialProps; - specialProps.append("QT_INSTALL_PREFIX"); - specialProps.append("QT_INSTALL_DATA"); - specialProps.append("QT_INSTALL_DOCS"); - specialProps.append("QT_INSTALL_HEADERS"); - specialProps.append("QT_INSTALL_LIBS"); - specialProps.append("QT_INSTALL_BINS"); - specialProps.append("QT_INSTALL_TESTS"); - specialProps.append("QT_INSTALL_PLUGINS"); - specialProps.append("QT_INSTALL_IMPORTS"); - specialProps.append("QT_INSTALL_TRANSLATIONS"); - specialProps.append("QT_INSTALL_CONFIGURATION"); - specialProps.append("QT_INSTALL_EXAMPLES"); - specialProps.append("QT_INSTALL_DEMOS"); + for (int i = 0; i < sizeof(propList)/sizeof(propList[0]); i++) + specialProps.append(QString::fromLatin1(propList[i].name)); specialProps.append("QMAKE_MKSPECS"); specialProps.append("QMAKE_VERSION"); #ifdef QT_VERSION_STR diff --git a/qmake/property.h b/qmake/property.h index d67d0ad09d..6195e482fb 100644 --- a/qmake/property.h +++ b/qmake/property.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -55,6 +56,9 @@ class QMakeProperty void initSettings(); QString keyBase(bool =true) const; QString value(QString, bool just_check); + + QHash m_values; + public: QMakeProperty(); ~QMakeProperty(); -- cgit v1.2.3 From 8e5eb1bddcfc71f70604c9d9916659e6cbc66845 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Feb 2012 18:56:11 +0100 Subject: look for features relative to spec only in advertized place that is, spec/../features/ (i.e., mkspecs/features/) - and not any directory up to the root. Change-Id: Ie5fdf2898fba5ac93583571edc24629471604798 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 48c5540076..545adced43 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -578,15 +578,12 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) feature_roots << Option::mkfile::qmakespec + QLatin1String("/features"); if(!Option::mkfile::qmakespec.isEmpty()) { QFileInfo specfi(Option::mkfile::qmakespec); - QDir specdir(specfi.absoluteFilePath()); - while(!specdir.isRoot()) { - if(!specdir.cdUp() || specdir.isRoot()) - break; - if(QFile::exists(specdir.path() + QLatin1String("/features"))) { + if (!specfi.isRoot()) { + QDir specdir(specfi.absolutePath()); + if (specdir.exists(QLatin1String("features"))) { for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) feature_roots << (specdir.path() + (*concat_it)); - break; } } } -- cgit v1.2.3 From 0bb99c6ff36ac78e29cde445400aa279a5b3d978 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Feb 2012 19:01:26 +0100 Subject: cosmetics: remove redundant conditional, add a comment & reshuffle code Change-Id: I71c7e18db63f3581b8c818ad178aeb4f6ccf9446 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 545adced43..6793ed3be6 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -530,9 +530,10 @@ static void qmake_error_msg(const QString &msg) */ QStringList qmake_feature_paths(QMakeProperty *prop=0) { + const QString mkspecs_concat = QLatin1String("/mkspecs"); + const QString base_concat = QLatin1String("/features"); QStringList concat; { - const QString base_concat = QLatin1String("/features"); switch(Option::target_mode) { case Option::TARG_MACX_MODE: //also a unix concat << base_concat + QLatin1String("/mac"); @@ -549,7 +550,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) } concat << base_concat; } - const QString mkspecs_concat = QLatin1String("/mkspecs"); + QStringList feature_roots; QByteArray mkspec_path = qgetenv("QMAKEFEATURES"); if(!mkspec_path.isNull()) @@ -574,9 +575,10 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) feature_roots << ((*it) + mkspecs_concat + (*concat_it)); } } - if(!Option::mkfile::qmakespec.isEmpty()) - feature_roots << Option::mkfile::qmakespec + QLatin1String("/features"); if(!Option::mkfile::qmakespec.isEmpty()) { + // The spec is already platform-dependent, so no subdirs here. + feature_roots << Option::mkfile::qmakespec + base_concat; + QFileInfo specfi(Option::mkfile::qmakespec); if (!specfi.isRoot()) { QDir specdir(specfi.absolutePath()); -- cgit v1.2.3 From 012f799254eedc610e2e33842e62d2a184b14fcc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 28 Feb 2012 20:57:38 +0100 Subject: revamp -sysroot and -hostprefix handling instead of being a variable added to the makespec (via qconfig.pri), QT_SYSROOT is now a property. the QT_INSTALL_... properties are now automatically prefixed with the sysroot; the raw values are available as QT_RAW_INSTALL_... - this is expected to cause the least migration effort for existing projects. -hostprefix and the new -hostbindir & -hostdatadir now feed the new QT_HOST_... properties. adapted the qmake feature files and the qtbase build system accordingly. Change-Id: Iaa9b65bc10d9fe9c4988d620c70a8ce72177f8d4 Reviewed-by: Marius Storm-Olsen --- configure | 103 +++++++++++++++++++++------------ dist/changes-5.0.0 | 6 +- mkspecs/features/default_pre.prf | 4 +- mkspecs/features/module.prf | 2 +- mkspecs/features/qt_config.prf | 2 +- mkspecs/features/qt_functions.prf | 4 +- mkspecs/features/qt_module.prf | 2 +- mkspecs/features/qt_module_config.prf | 22 +++---- qmake/generators/makefile.cpp | 2 +- qmake/generators/win32/msvc_vcproj.cpp | 10 ++-- qmake/project.cpp | 6 +- qmake/property.cpp | 48 ++++++++++----- qtbase.pro | 8 +-- src/corelib/global/qlibraryinfo.cpp | 44 ++++++++++++-- src/corelib/global/qlibraryinfo.h | 12 ++++ src/tools/moc/moc.pro | 2 +- src/tools/rcc/rcc.pro | 2 +- src/tools/uic/uic.pro | 2 +- tools/configure/configureapp.cpp | 78 +++++++++++++++++-------- 19 files changed, 243 insertions(+), 116 deletions(-) diff --git a/configure b/configure index 7aa8adaa43..de65cdc7bc 100755 --- a/configure +++ b/configure @@ -825,7 +825,10 @@ QT_INSTALL_TRANSLATIONS= QT_INSTALL_SETTINGS= QT_INSTALL_EXAMPLES= QT_INSTALL_TESTS= +CFG_SYSROOT= QT_HOST_PREFIX= +QT_HOST_BINS= +QT_HOST_DATA= #flags for SQL drivers QT_CFLAGS_PSQL= @@ -978,7 +981,7 @@ while [ "$#" -gt 0 ]; do shift VAL=$1 ;; - -prefix|-docdir|-headerdir|-plugindir|-importdir|-datadir|-libdir|-bindir|-translationdir|-sysconfdir|-examplesdir|-testsdir|-depths|-make|-nomake|-platform|-xplatform|-sdk|-arch|-host-arch|-mysql_config|-sysroot) + -prefix|-docdir|-headerdir|-plugindir|-importdir|-datadir|-libdir|-bindir|-translationdir|-sysconfdir|-examplesdir|-testsdir|-depths|-make|-nomake|-platform|-xplatform|-sdk|-arch|-host-arch|-mysql_config|-sysroot|-hostdatadir|-hostbindir) VAR=`echo $1 | sed "s,^-\(.*\),\1,"` shift VAL="$1" @@ -1169,6 +1172,12 @@ while [ "$#" -gt 0 ]; do hostprefix) QT_HOST_PREFIX="$VAL" ;; + hostdatadir) + QT_HOST_DATA="$VAL" + ;; + hostbindir) + QT_HOST_BINS="$VAL" + ;; force-pkg-config) QT_FORCE_PKGCONFIG=yes ;; @@ -3116,6 +3125,40 @@ if [ -z "$QT_INSTALL_TESTS" ]; then #default fi QT_INSTALL_TESTS=`"$relpath/config.tests/unix/makeabs" "$QT_INSTALL_TESTS"` +#------- host paths -------- + +if [ -z "$QT_HOST_PREFIX" ]; then + QT_HOST_PREFIX=$QT_INSTALL_PREFIX + haveHpx=false +else + QT_HOST_PREFIX=`"$relpath/config.tests/unix/makeabs" "$QT_HOST_PREFIX"` + haveHpx=true +fi + +if [ -z "$QT_HOST_BINS" ]; then #default + if $haveHpx; then + if [ "$CFG_PREFIX_INSTALL" = "no" ]; then + if [ "$BUILD_ON_MAC" = "yes" ]; then + QT_HOST_BINS="/Developer/Applications/Qt" + fi + fi + [ -z "$QT_HOST_BINS" ] && QT_HOST_BINS="$QT_HOST_PREFIX/bin" #fallback + else + QT_HOST_BINS="$QT_INSTALL_BINS" + fi +fi +QT_HOST_BINS=`"$relpath/config.tests/unix/makeabs" "$QT_HOST_BINS"` + +if [ -z "$QT_HOST_DATA" ]; then #default + if $haveHpx; then + QT_HOST_DATA="$QT_HOST_PREFIX" + else + QT_HOST_DATA="$QT_INSTALL_DATA" + fi +else + QT_HOST_DATA=`"$relpath/config.tests/unix/makeabs" "$QT_HOST_DATA"` +fi + #------------------------------------------------------------------------------- # help - interactive parts of the script _after_ this section please #------------------------------------------------------------------------------- @@ -3233,6 +3276,7 @@ cat < ....... Tests will be installed to (default PREFIX/tests) +EOF +if [ "$PLATFORM_QWS" = "yes" -o "$PLATFORM_QPA" = "yes" ]; then +cat < .. Host executables will be installed to + (default HOSTPREFIX/bin) + -hostdatadir . Data used by qmake will be installed to + (default HOSTPREFIX) +EOF +fi +cat <> "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" <> "$outpath/src/corelib/global/qconfig.cpp.new" <>"$QTCONFIG.tmp" echo `basename "$XQMAKESPEC"` \{ >>"$QTCONFIG.tmp" - echo " QT_SYSROOT += \$\$quote($CFG_SYSROOT)" >>"$QTCONFIG.tmp" - echo " QMAKE_CFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp" - echo " QMAKE_CXXFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp" - echo " QMAKE_LFLAGS += --sysroot=\$\$QT_SYSROOT" >>"$QTCONFIG.tmp" + echo " QMAKE_CFLAGS += --sysroot=\$\$[QT_SYSROOT]" >>"$QTCONFIG.tmp" + echo " QMAKE_CXXFLAGS += --sysroot=\$\$[QT_SYSROOT]" >>"$QTCONFIG.tmp" + echo " QMAKE_LFLAGS += --sysroot=\$\$[QT_SYSROOT]" >>"$QTCONFIG.tmp" echo "}" >> "$QTCONFIG.tmp" echo >> "$QTCONFIG.tmp" fi diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index e1f1f07203..ca9047b682 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -202,7 +202,11 @@ information about a particular change. - qmake * Projects which explicitly set an empty TARGET are considered broken now. - * several functions and built-in variables were modified to return normalized paths. + * Configure's -sysroot and -hostprefix are now handled slightly differently. + The QT_INSTALL_... properties are now automatically prefixed with the sysroot; + the raw values are available as QT_RAW_INSTALL_... and the sysroot as QT_SYSROOT. + The new QT_HOST_... properties can be used to refer to the Qt host tools. + * Several functions and built-in variables were modified to return normalized paths. - QTextCodecPlugin has been removed since it is no longer used. All text codecs are now built into QtCore. diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf index 1a56787d15..aa706393a5 100644 --- a/mkspecs/features/default_pre.prf +++ b/mkspecs/features/default_pre.prf @@ -26,10 +26,10 @@ CONFIG = lex yacc warn_on debug uic resources $$CONFIG # can we tell syncqt to do a -developer-build win32 { CMP_QDIR = $$upper($$QTDIR) - CMP_INSTALL_PREFIX = $$upper($$[QT_INSTALL_PREFIX]) + CMP_INSTALL_PREFIX = $$upper($$[QT_HOST_PREFIX]) } else { CMP_QDIR = $$QTDIR - CMP_INSTALL_PREFIX = $$[QT_INSTALL_PREFIX] + CMP_INSTALL_PREFIX = $$[QT_HOST_PREFIX] } contains(CMP_QDIR, $$CMP_INSTALL_PREFIX):QTFWD = -qtdir $$QTDIR -module-fwd $$QTDIR/mkspecs/modules -developer-build unset(CMP_QDIR) diff --git a/mkspecs/features/module.prf b/mkspecs/features/module.prf index 85639f0345..d95c7a418d 100644 --- a/mkspecs/features/module.prf +++ b/mkspecs/features/module.prf @@ -1,5 +1,5 @@ !isEmpty(MODULE_PRI) { - pritarget.path = $$[QT_INSTALL_DATA]/mkspecs/modules + pritarget.path = $$[QT_HOST_DATA]/mkspecs/modules pritarget.files = $$MODULE_PRI INSTALLS += pritarget } else { diff --git a/mkspecs/features/qt_config.prf b/mkspecs/features/qt_config.prf index 8441728815..8d0dcce92c 100644 --- a/mkspecs/features/qt_config.prf +++ b/mkspecs/features/qt_config.prf @@ -8,7 +8,7 @@ exists($$_QMAKE_CACHE_) { isEmpty(QMAKE_QT_CONFIG)|!exists($$QMAKE_QT_CONFIG) { !isEmpty(QT_BUILD_TREE):QMAKE_QT_CONFIG = $$QT_BUILD_TREE else:exists($$_QMAKE_CACHE_):QMAKE_QT_CONFIG = $$fromfile($$_QMAKE_CACHE_, QT_BUILD_TREE) - isEmpty(QMAKE_QT_CONFIG):QMAKE_QT_CONFIG = $$[QT_INSTALL_DATA] + isEmpty(QMAKE_QT_CONFIG):QMAKE_QT_CONFIG = $$[QT_HOST_DATA] QMAKE_QT_CONFIG = $$QMAKE_QT_CONFIG/mkspecs/qconfig.pri } !exists($$QMAKE_QT_CONFIG)|!include($$QMAKE_QT_CONFIG, "", true) { diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 65eec35bfc..31b28156e8 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -132,7 +132,7 @@ defineTest(qtAddModule) { isEmpty(LINKAGE) { # Make sure we can link to uninstalled libraries - !isEqual(MODULE_LIBS, $$[QT_INSTALL_LIBS]) { + !isEqual(MODULE_LIBS, $$[QT_INSTALL_LIBS]) { ### XXX QMAKE_LIBDIR *= $$MODULE_LIBS unix:!mac:QMAKE_LFLAGS *= "-Wl,-rpath-link,$$MODULE_LIBS" } @@ -164,7 +164,7 @@ defineTest(qtAddModule) { # variable, default defineTest(qtPrepareTool) { - MODBASE = $$[QT_INSTALL_BINS] + MODBASE = $$[QT_HOST_BINS] !isEmpty(QT_BUILD_TREE):MODBASE = $$QT_BUILD_TREE/bin count(ARGS, 2, greaterThan) { isEmpty(QT.$${3}.bins):warning("No QT.$${3}.bins, module path ignored for qtPrepareTool($$1, $$2, $$3)") diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index aee95295e8..b71ef61252 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -8,7 +8,7 @@ isEmpty(QMAKE_QT_MODULE)|!exists($$QMAKE_QT_MODULE) { !exists($$QMAKE_QT_MODULE):exists($$QMAKE_CACHE_DIR/mkspecs/qmodule.pri):QMAKE_QT_MODULE = $$QMAKE_CACHE_DIR/mkspecs/qmodule.pri !exists($$QMAKE_QT_MODULE):exists($$QMAKE_CACHE_DIR/qtbase/mkspecs/qmodule.pri):QMAKE_QT_MODULE = $$QMAKE_CACHE_DIR/qtbase/mkspecs/qmodule.pri !exists($$QMAKE_QT_MODULE):if(!isEmpty(QT_BUILD_TREE) & exists($$QT_BUILD_TREE/mkspecs/qmodule.pri)):QMAKE_QT_MODULE = $$QT_BUILD_TREE/mkspecs/qmodule.pri - !exists($$QMAKE_QT_MODULE):exists($$[QT_INSTALL_DATA]/mkspecs/qmodule.pri):QMAKE_QT_MODULE = $$[QT_INSTALL_DATA]/mkspecs/qmodule.pri + !exists($$QMAKE_QT_MODULE):exists($$[QT_HOST_DATA]/mkspecs/qmodule.pri):QMAKE_QT_MODULE = $$[QT_HOST_DATA]/mkspecs/qmodule.pri } !contains(QMAKE_INTERNAL_INCLUDED_FILES, .*qmodule\\.pri) { diff --git a/mkspecs/features/qt_module_config.prf b/mkspecs/features/qt_module_config.prf index a8439198df..ad6990657b 100644 --- a/mkspecs/features/qt_module_config.prf +++ b/mkspecs/features/qt_module_config.prf @@ -118,18 +118,18 @@ load(qt_installs) unix { CONFIG += create_libtool create_pc explicitlib - QMAKE_LIBTOOL_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PRL_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET - QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] + QMAKE_LIBTOOL_LIBDIR = $$[QT_RAW_INSTALL_LIBS] + QMAKE_PRL_LIBDIR = $$[QT_RAW_INSTALL_LIBS] ### XXX + QMAKE_PKGCONFIG_LIBDIR = $$[QT_RAW_INSTALL_LIBS] + QMAKE_PKGCONFIG_INCDIR = $$[QT_RAW_INSTALL_HEADERS]/$$TARGET + QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_RAW_INSTALL_HEADERS] QMAKE_PKGCONFIG_DESTDIR = pkgconfig include_replace.match = $$QMAKE_INCDIR_QT - include_replace.replace = $$[QT_INSTALL_HEADERS] + include_replace.replace = $$[QT_RAW_INSTALL_HEADERS] lib_replace.match = $$QMAKE_LIBDIR_QT - lib_replace.replace = $$[QT_INSTALL_LIBS] + lib_replace.replace = $$[QT_RAW_INSTALL_LIBS] prefix_replace.match = $$QT_BUILD_TREE - prefix_replace.replace = $$[QT_INSTALL_PREFIX] + prefix_replace.replace = $$[QT_RAW_INSTALL_PREFIX] QMAKE_PRL_INSTALL_REPLACE += include_replace lib_replace QMAKE_LIBTOOL_INSTALL_REPLACE += include_replace lib_replace QMAKE_PKGCONFIG_INSTALL_REPLACE += include_replace lib_replace prefix_replace @@ -137,9 +137,9 @@ unix { win32-g++* { CONFIG += create_pc - QMAKE_PKGCONFIG_LIBDIR = $$[QT_INSTALL_LIBS] - QMAKE_PKGCONFIG_INCDIR = $$[QT_INSTALL_HEADERS]/$$TARGET - QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_INSTALL_HEADERS] + QMAKE_PKGCONFIG_LIBDIR = $$[QT_RAW_INSTALL_LIBS] + QMAKE_PKGCONFIG_INCDIR = $$[QT_RAW_INSTALL_HEADERS]/$$TARGET + QMAKE_PKGCONFIG_CFLAGS = -I$$[QT_RAW_INSTALL_HEADERS] QMAKE_PKGCONFIG_DESTDIR = pkgconfig } diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 59a615e63a..45cb250fe1 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -3178,7 +3178,7 @@ MakefileGenerator::pkgConfigPrefix() const { if(!project->isEmpty("QMAKE_PKGCONFIG_PREFIX")) return project->first("QMAKE_PKGCONFIG_PREFIX"); - return QLibraryInfo::location(QLibraryInfo::PrefixPath); + return QLibraryInfo::rawLocation(QLibraryInfo::PrefixPath); } QString diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 109b50fd94..434d4b4559 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1575,11 +1575,11 @@ QString VcprojGenerator::findTemplate(QString file) QString ret; if(!exists((ret = file)) && !exists((ret = QString(Option::mkfile::qmakespec + "/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc.net/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2002/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2003/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2005/" + file))) && - !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::DataPath) + "/win32-msvc2008/" + file)))) + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::HostDataPath) + "/win32-msvc.net/" + file))) && + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::HostDataPath) + "/win32-msvc2002/" + file))) && + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::HostDataPath) + "/win32-msvc2003/" + file))) && + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::HostDataPath) + "/win32-msvc2005/" + file))) && + !exists((ret = QString(QLibraryInfo::location(QLibraryInfo::HostDataPath) + "/win32-msvc2008/" + file)))) return ""; debug_msg(1, "Generator: MSVC.NET: Found template \'%s\'", ret.toLatin1().constData()); return ret; diff --git a/qmake/project.cpp b/qmake/project.cpp index 52f2206410..bfd4511f2f 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -592,7 +592,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) } for(QStringList::Iterator concat_it = concat.begin(); concat_it != concat.end(); ++concat_it) - feature_roots << (QLibraryInfo::location(QLibraryInfo::DataPath) + + feature_roots << (QLibraryInfo::location(QLibraryInfo::HostDataPath) + mkspecs_concat + (*concat_it)); return feature_roots; } @@ -607,7 +607,7 @@ QStringList qmake_mkspec_paths() for(QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) ret << ((*it) + concat); } - ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; + ret << QLibraryInfo::location(QLibraryInfo::HostDataPath) + concat; return ret; } @@ -3113,7 +3113,7 @@ QStringList &QMakeProject::values(const QString &_var, QHash LastHostPath) { + QString sysroot = rawLocation(SysrootPath); + if (!sysroot.isEmpty() && ret.length() > 2 && ret.at(1) == QLatin1Char(':') + && (ret.at(2) == QLatin1Char('/') || ret.at(2) == QLatin1Char('\\'))) + ret.replace(0, 2, sysroot); // Strip out the drive on Windows targets + else + ret.prepend(sysroot); + } + + return ret; +} + +QString +QLibraryInfo::rawLocation(LibraryLocation loc) +{ +#else +# define rawLocation location +#endif QString ret; if(!QLibraryInfoPrivate::configuration()) { const char *path = 0; @@ -284,11 +311,19 @@ QLibraryInfo::location(LibraryLocation loc) if (QDir::isRelativePath(ret)) { QString baseDir; - if (loc == PrefixPath) { - // we make the prefix path absolute to the executable's directory #ifdef QT_BUILD_QMAKE + if (loc == HostPrefixPath || loc == PrefixPath) { + // We make the prefix path absolute to the executable's directory. + // loc == PrefixPath while a sysroot is set would make no sense here. baseDir = QFileInfo(qmake_libraryInfoFile()).absolutePath(); + } else if (loc == SysrootPath) { + // The sysroot is bare + return ret; + } else if (loc > SysrootPath && loc <= LastHostPath) { + // We make any other host path absolute to the host prefix directory. + baseDir = rawLocation(HostPrefixPath); #else + if (loc == PrefixPath) { if (QCoreApplication::instance()) { #ifdef Q_OS_MAC CFBundleRef bundleRef = CFBundleGetMainBundle(); @@ -300,6 +335,7 @@ QLibraryInfo::location(LibraryLocation loc) } } #endif + // We make the prefix path absolute to the executable's directory. baseDir = QCoreApplication::applicationDirPath(); } else { baseDir = QDir::currentPath(); @@ -307,7 +343,7 @@ QLibraryInfo::location(LibraryLocation loc) #endif } else { // we make any other path absolute to the prefix directory - baseDir = location(PrefixPath); + baseDir = rawLocation(PrefixPath); } ret = QDir::cleanPath(baseDir + QLatin1Char('/') + ret); } diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index f6234d1eb4..d180e63198 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -77,9 +77,21 @@ public: TranslationsPath, ExamplesPath, TestsPath, + // Insert new values above this line +#ifdef QT_BUILD_QMAKE + // These are not subject to binary compatibility constraints + SysrootPath, + HostPrefixPath, + HostBinariesPath, + HostDataPath, + LastHostPath = HostDataPath, +#endif SettingsPath = 100 }; static QString location(LibraryLocation); // ### Qt 5: consider renaming it to path() +#ifdef QT_BUILD_QMAKE + static QString rawLocation(LibraryLocation); +#endif private: QLibraryInfo(); diff --git a/src/tools/moc/moc.pro b/src/tools/moc/moc.pro index 3ee507855c..5c96c96a4c 100644 --- a/src/tools/moc/moc.pro +++ b/src/tools/moc/moc.pro @@ -13,6 +13,6 @@ HEADERS += qdatetime_p.h SOURCES += main.cpp include(../bootstrap/bootstrap.pri) -target.path=$$[QT_INSTALL_BINS] +target.path = $$[QT_HOST_BINS] INSTALLS += target load(qt_targets) diff --git a/src/tools/rcc/rcc.pro b/src/tools/rcc/rcc.pro index 6c78642406..e87ef605b9 100644 --- a/src/tools/rcc/rcc.pro +++ b/src/tools/rcc/rcc.pro @@ -11,6 +11,6 @@ HEADERS += ../../corelib/kernel/qcorecmdlineargs_p.h SOURCES += main.cpp include(../bootstrap/bootstrap.pri) -target.path=$$[QT_INSTALL_BINS] +target.path = $$[QT_HOST_BINS] INSTALLS += target load(qt_targets) diff --git a/src/tools/uic/uic.pro b/src/tools/uic/uic.pro index 7a95db861f..0acc6e77c8 100644 --- a/src/tools/uic/uic.pro +++ b/src/tools/uic/uic.pro @@ -22,6 +22,6 @@ linux-g++-maemo { include(../bootstrap/bootstrap.pri) -target.path=$$[QT_INSTALL_BINS] +target.path = $$[QT_HOST_BINS] INSTALLS += target load(qt_targets) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index e4c9bb2010..504728abc8 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1063,11 +1063,33 @@ void Configure::parseCmdLine() dictionary[ "QT_INSTALL_TESTS" ] = configCmdLine.at(i); } + else if (configCmdLine.at(i) == "-sysroot") { + ++i; + if (i == argCount) + break; + dictionary[ "CFG_SYSROOT" ] = configCmdLine.at(i); + } + else if (configCmdLine.at(i) == "-hostprefix") { + ++i; + if (i == argCount || configCmdLine.at(i).startsWith('-')) + dictionary[ "QT_HOST_PREFIX" ] = dictionary[ "QT_BUILD_TREE" ]; + else + dictionary[ "QT_HOST_PREFIX" ] = configCmdLine.at(i); + } + + else if (configCmdLine.at(i) == "-hostbindir") { ++i; if (i == argCount) break; - dictionary[ "QT_HOST_PREFIX" ] = configCmdLine.at(i); + dictionary[ "QT_HOST_BINS" ] = configCmdLine.at(i); + } + + else if (configCmdLine.at(i) == "-hostdatadir") { + ++i; + if (i == argCount) + break; + dictionary[ "QT_HOST_DATA" ] = configCmdLine.at(i); } else if (configCmdLine.at(i) == "-make") { @@ -2381,6 +2403,16 @@ void Configure::generateOutputVars() if (!dictionary[ "QT_INSTALL_TESTS" ].size()) dictionary[ "QT_INSTALL_TESTS" ] = qipempty ? "" : fixSeparators(dictionary[ "QT_INSTALL_PREFIX" ] + "/tests"); + bool haveHpx = false; + if (dictionary[ "QT_HOST_PREFIX" ].isEmpty()) + dictionary[ "QT_HOST_PREFIX" ] = dictionary[ "QT_INSTALL_PREFIX" ]; + else + haveHpx = true; + if (dictionary[ "QT_HOST_BINS" ].isEmpty()) + dictionary[ "QT_HOST_BINS" ] = haveHpx ? fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/bin") : dictionary[ "QT_INSTALL_BINS" ]; + if (dictionary[ "QT_HOST_DATA" ].isEmpty()) + dictionary[ "QT_HOST_DATA" ] = haveHpx ? dictionary[ "QT_HOST_PREFIX" ] : dictionary[ "QT_INSTALL_DATA" ]; + if (dictionary.contains("XQMAKESPEC") && dictionary[ "XQMAKESPEC" ].startsWith("linux")) dictionary[ "QMAKE_RPATHDIR" ] = dictionary[ "QT_INSTALL_LIBS" ]; @@ -2599,6 +2631,17 @@ void Configure::generateCachefile() << "QT_MINOR_VERSION = " << dictionary["VERSION_MINOR"] << endl << "QT_PATCH_VERSION = " << dictionary["VERSION_PATCH"] << endl; + if (!dictionary["CFG_SYSROOT"].isEmpty()) { + QString targetSpec = dictionary.contains("XQMAKESPEC") ? dictionary[ "XQMAKESPEC" ] : dictionary[ "QMAKESPEC" ]; + configStream << endl + << "# sysroot" << endl + << targetSpec << " {" << endl + << " QMAKE_CFLAGS += --sysroot=$$[QT_SYSROOT]" << endl + << " QMAKE_CXXFLAGS += --sysroot=$$[QT_SYSROOT]" << endl + << " QMAKE_LFLAGS += --sysroot=$$[QT_SYSROOT]" << endl + << "}" << endl; + } + configStream.flush(); configFile.close(); } @@ -2854,10 +2897,8 @@ void Configure::generateConfigfiles() << endl << "/* Build date */" << endl << "static const char qt_configure_installation [11 + 12] = \"qt_instdate=" << QDate::currentDate().toString(Qt::ISODate) << "\";" << endl - << endl; - if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) - tmpStream << "#if !defined(QT_BOOTSTRAPPED) && !defined(QT_BUILD_QMAKE)" << endl; - tmpStream << "static const char qt_configure_prefix_path_strs[][12 + 512] = {" << endl + << endl + << "static const char qt_configure_prefix_path_strs[][12 + 512] = {" << endl << " \"qt_prfxpath=" << escapeSeparators(dictionary["QT_INSTALL_PREFIX"]) << "\"," << endl << " \"qt_docspath=" << escapeSeparators(dictionary["QT_INSTALL_DOCS"]) << "\"," << endl << " \"qt_hdrspath=" << escapeSeparators(dictionary["QT_INSTALL_HEADERS"]) << "\"," << endl @@ -2869,27 +2910,16 @@ void Configure::generateConfigfiles() << " \"qt_trnspath=" << escapeSeparators(dictionary["QT_INSTALL_TRANSLATIONS"]) << "\"," << endl << " \"qt_xmplpath=" << escapeSeparators(dictionary["QT_INSTALL_EXAMPLES"]) << "\"," << endl << " \"qt_tstspath=" << escapeSeparators(dictionary["QT_INSTALL_TESTS"]) << "\"," << endl + << "#ifdef QT_BUILD_QMAKE" << endl + << " \"qt_ssrtpath=" << escapeSeparators(dictionary["CFG_SYSROOT"]) << "\"," << endl + << " \"qt_hpfxpath=" << escapeSeparators(dictionary["QT_HOST_PREFIX"]) << "\"," << endl + << " \"qt_hbinpath=" << escapeSeparators(dictionary["QT_HOST_BINS"]) << "\"," << endl + << " \"qt_hdatpath=" << escapeSeparators(dictionary["QT_HOST_DATA"]) << "\"," << endl + << "#endif" << endl << "};" << endl //<< "static const char qt_configure_settings_path_str [256] = \"qt_stngpath=" << escapeSeparators(dictionary["QT_INSTALL_SETTINGS"]) << "\";" << endl - ; - if (!dictionary[ "QT_HOST_PREFIX" ].isNull()) { - tmpStream << "#else" << endl - << "static const char qt_configure_prefix_path_strs[][12 + 512] = {" << endl - << " \"qt_prfxpath=" << escapeSeparators(dictionary[ "QT_HOST_PREFIX" ]) << "\";" << endl - << " \"qt_docspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/doc", true) <<"\"," << endl - << " \"qt_hdrspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/include", true) <<"\"," << endl - << " \"qt_libspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/lib", true) <<"\"," << endl - << " \"qt_binspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/bin", true) <<"\"," << endl - << " \"qt_plugpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/plugins", true) <<"\"," << endl - << " \"qt_impspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/imports", true) <<"\"," << endl - << " \"qt_datapath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ], true) <<"\"," << endl - << " \"qt_trnspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/translations", true) <<"\"," << endl - << " \"qt_xmplpath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/example", true) <<"\"," << endl - << " \"qt_tstspath=" << fixSeparators(dictionary[ "QT_HOST_PREFIX" ] + "/tests", true) <<"\"," << endl - << "};" << endl - << "#endif //QT_BOOTSTRAPPED" << endl; - } - tmpStream << "/* strlen( \"qt_lcnsxxxx\") == 12 */" << endl + << endl + << "/* strlen( \"qt_lcnsxxxx\") == 12 */" << endl << "#define QT_CONFIGURE_LICENSEE qt_configure_licensee_str + 12;" << endl << "#define QT_CONFIGURE_LICENSED_PRODUCTS qt_configure_licensed_products_str + 12;" << endl //<< "#define QT_CONFIGURE_SETTINGS_PATH qt_configure_settings_path_str + 12;" << endl -- cgit v1.2.3 From 1e92e8d385cd689dfd26c60d3c98ae93bb99d466 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 20:21:41 +0100 Subject: fix configure -redo -redo must be the first argument (except -srcdir, which we treat differently), so let's pass the user arguments first. Change-Id: I5da37d1a6e1aec67449daf64b8bd2ffcc0b075a4 Reviewed-by: Marius Storm-Olsen --- configure.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.bat b/configure.bat index e872de2797..f0b6ce5310 100644 --- a/configure.bat +++ b/configure.bat @@ -117,5 +117,5 @@ if errorlevel 1 (cd ..\.. & exit /b 1) cd ..\.. :conf -configure.exe -srcdir %QTSRC% %nosyncqt% %* +configure.exe -srcdir %QTSRC% %* %nosyncqt% :exit -- cgit v1.2.3 From d9bf972e2b5f6bace5b7be350a70b4207e320692 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 19:38:03 +0100 Subject: merge Makefile.win32-g++{,-sh} the only difference is in the copy & del commands. the msys tools are tolerant about windows paths, so this just works. the in-makefile variant detection is stolen from tools/configure/. Change-Id: Ia283c1fe2e2aaa8cd5b1dfd7ae29244115f07d65 Reviewed-by: Marius Storm-Olsen --- qmake/Makefile.win32-g++ | 36 +++- qmake/Makefile.win32-g++-sh | 343 --------------------------------------- tools/configure/configureapp.cpp | 6 +- 3 files changed, 32 insertions(+), 353 deletions(-) delete mode 100644 qmake/Makefile.win32-g++-sh diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 585061ed26..d9c3b0300a 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -2,12 +2,38 @@ ifeq "$(SOURCE_PATH)" "" SOURCE_PATH = .. endif -#cmd version - ifeq "$(BUILD_PATH)" "" BUILD_PATH = .. endif +# SHELL is the full path of sh.exe, unless +# 1) it is found in the current directory +# 2) it is not found at all +# 3) it is overridden on the command line with an existing file +# ... otherwise it is always sh.exe. Specifically, SHELL from the +# environment has no effect. +# +# This check will fail if SHELL is explicitly set to a not +# sh-compatible shell. This is not a problem, because configure.exe +# will not do that. +ifeq ($(SHELL), sh.exe) + ifeq ($(wildcard $(CURDIR)/sh.exe), ) + SH = 0 + else + SH = 1 + endif +else + SH = 1 +endif + +ifeq ($(SH), 1) + COPY = cp + DEL = rm -f +else + COPY = copy + DEL = del /f +endif + # # specific stuff for mingw g++ make # @@ -101,16 +127,16 @@ QTOBJS= \ qmake.exe: $(OBJS) $(QTOBJS) $(LINKQMAKE) - -copy qmake.exe $(BUILD_PATH)\bin\qmake.exe + -$(COPY) qmake.exe $(BUILD_PATH)\bin\qmake.exe Makefile: Makefile.win32-g++ @echo "Out of date, please rerun configure" clean:: - -del $(OBJS) $(QTOBJS) $(ADDCLEAN) + -$(DEL) $(OBJS) $(QTOBJS) $(ADDCLEAN) distclean:: clean - -del qmake + -$(DEL) qmake.exe .c.o: $(CXX) $(CFLAGS) $< diff --git a/qmake/Makefile.win32-g++-sh b/qmake/Makefile.win32-g++-sh deleted file mode 100644 index 6dfb486375..0000000000 --- a/qmake/Makefile.win32-g++-sh +++ /dev/null @@ -1,343 +0,0 @@ -ifeq "$(SOURCE_PATH)" "" -SOURCE_PATH = .. -endif - -#sh version - -ifeq "$(BUILD_PATH)" "" -BUILD_PATH = .. -endif - -# -# specific stuff for mingw g++ make -# -CXX = g++ -CFLAGS = -c -o$@ -O \ - -I. -Igenerators -Igenerators/unix \ - -Igenerators/win32 -Igenerators/mac \ - -Igenerators/integrity \ - -I$(BUILD_PATH)/include -I$(BUILD_PATH)/include/QtCore -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION) -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION)/QtCore \ - -I$(SOURCE_PATH)/include -I$(SOURCE_PATH)/include/QtCore -I$(SOURCE_PATH)/include/QtCore/$(QT_VERSION) -I$(SOURCE_PATH)/include/QtCore/$(QT_VERSION)/QtCore \ - -I$(BUILD_PATH)/src/corelib/global \ - -I$(BUILD_PATH)/src/corelib/xml \ - -I$(SOURCE_PATH)/mkspecs/win32-g++ \ - -I$(SOURCE_PATH)/tools/shared \ - -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT \ - -DQT_NODLL -DQT_NO_STL -DQT_NO_COMPRESS -DUNICODE -DHAVE_QCONFIG_CPP \ - -DQT_BUILD_QMAKE -DQT_NO_THREAD -DQT_NO_QOBJECT -DQT_NO_GEOM_VARIANT -DQT_NO_DATASTREAM \ - -DQT_BOOTSTRAPPED -CXXFLAGS = $(CFLAGS) -LFLAGS = -static-libgcc -s -LIBS = -lole32 -luuid -ladvapi32 -lkernel32 -LINKQMAKE = g++ $(LFLAGS) -o qmake.exe $(OBJS) $(QTOBJS) $(LIBS) -ADDCLEAN = - - -#qmake code -OBJS = project.o main.o makefile.o unixmake.o unixmake2.o mingw_make.o \ - option.o winmakefile.o projectgenerator.o property.o meta.o \ - makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \ - borland_bmake.o msvc_nmake.o msvc_vcproj.o msvc_vcxproj.o \ - msvc_objectmodel.o msbuild_objectmodel.o registry.o gbuild.o - -ifdef QMAKE_OPENSOURCE_EDITION -CFLAGS += -DQMAKE_OPENSOURCE_EDITION -endif - -#qt code -QTOBJS= \ - qbitarray.o \ - qbuffer.o \ - qbytearray.o \ - qcryptographichash.o \ - qvsnprintf.o \ - qbytearraymatcher.o \ - qconfig.o \ - qdatetime.o \ - qdir.o \ - qdiriterator.o \ - qfile.o \ - qtemporaryfile.o \ - qfileinfo.o \ - qabstractfileengine.o \ - qfilesystementry.o \ - qfilesystemengine.o \ - qfilesystemengine_win.o \ - qfilesystemiterator_win.o \ - qfsfileengine.o \ - qfsfileengine_iterator.o \ - qfsfileengine_win.o \ - qglobal.o \ - qhash.o \ - qiodevice.o \ - qlibraryinfo.o \ - qlist.o \ - qlinkedlist.o \ - qlocale.o \ - qlocale_tools.o \ - qlocale_win.o \ - qmalloc.o \ - qmap.o \ - qregexp.o \ - qtextcodec.o \ - qutfcodec.o \ - qstring.o \ - qstringlist.o \ - qsystemlibrary.o \ - qsystemerror.o \ - qtextstream.o \ - quuid.o \ - qvector.o \ - qurl.o \ - qsettings.o \ - qsettings_win.o \ - qvariant.o \ - qmetatype.o \ - qxmlstream.o \ - qxmlutils.o \ - qnumeric.o \ - qlogging.o - -qmake.exe: $(OBJS) $(QTOBJS) - $(LINKQMAKE) - -cp qmake.exe $(BUILD_PATH)/bin/qmake.exe - -Makefile: Makefile.win32-g++-sh - @echo "Out of date, please rerun configure" - -clean:: - -del $(OBJS) $(QTOBJS) $(ADDCLEAN) - -distclean:: clean - -del qmake - -.c.o: - $(CXX) $(CFLAGS) $< - -.cpp.o: - $(CXX) $(CXXFLAGS) $< - -qconfig.o: $(BUILD_PATH)/src/corelib/global/qconfig.cpp - $(CXX) $(CXXFLAGS) $(BUILD_PATH)/src/corelib/global/qconfig.cpp - -qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp - -qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp - -qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp - -qurl.o: $(SOURCE_PATH)/src/corelib/io/qurl.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qurl.cpp - -qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp - -qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp - -qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp - -qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp - -qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp - -qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp - -qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp - -qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qhash.cpp - -qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp - -qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp - -qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp - -qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp - -qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp - -qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp - -qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp - -qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp - -qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp - -quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp - -qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp - -qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlist.cpp - -qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp - -qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp - -qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp - -qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp - -qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp - -qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp - -qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp - -qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp - -qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp - -qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp - -qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp - -qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp - -qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp - -qvector.o: $(SOURCE_PATH)/src/corelib/tools/qvector.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvector.cpp - -qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp - -qdir.o: $(SOURCE_PATH)/src/corelib/io/qdir.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdir.cpp - -qdiriterator.o: $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp - -qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp - -qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp - -qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp - -qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp - -qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp - -qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp - -qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp - -makefile.o: $(SOURCE_PATH)/qmake/generators/makefile.cpp - $(CXX) $(CXXFLAGS) generators/makefile.cpp - -unixmake.o: $(SOURCE_PATH)/qmake/generators/unix/unixmake.cpp - $(CXX) $(CXXFLAGS) generators/unix/unixmake.cpp - -unixmake2.o: $(SOURCE_PATH)/qmake/generators/unix/unixmake2.cpp - $(CXX) $(CXXFLAGS) generators/unix/unixmake2.cpp - -winmakefile.o: $(SOURCE_PATH)/qmake/generators/win32/winmakefile.cpp - $(CXX) $(CXXFLAGS) generators/win32/winmakefile.cpp - -borland_bmake.o: $(SOURCE_PATH)/qmake/generators/win32/borland_bmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/borland_bmake.cpp - -mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp - $(CXX) $(CXXFLAGS) generators/win32/mingw_make.cpp - -msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp - -msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp - -msvc_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_objectmodel.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp - -msvc_vcxproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcxproj.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_vcxproj.cpp - -msbuild_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msbuild_objectmodel.cpp - $(CXX) $(CXXFLAGS) generators/win32/msbuild_objectmodel.cpp - -registry.o: $(SOURCE_PATH)/tools/shared/windows/registry.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/tools/shared/windows/registry.cpp - -gbuild.o: $(SOURCE_PATH)/qmake/generators/integrity/gbuild.cpp - $(CXX) $(CXXFLAGS) generators/integrity/gbuild.cpp - -project.o: $(SOURCE_PATH)/qmake/project.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) project.cpp - -meta.o: $(SOURCE_PATH)/qmake/meta.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) meta.cpp - -main.o: $(SOURCE_PATH)/qmake/main.cpp $(SOURCE_PATH)/qmake/project.h - $(CXX) $(CXXFLAGS) main.cpp - -option.o: $(SOURCE_PATH)/qmake/option.cpp $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) option.cpp - -property.o: $(SOURCE_PATH)/qmake/property.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) property.cpp - -projectgenerator.o: $(SOURCE_PATH)/qmake/generators/projectgenerator.cpp - $(CXX) $(CXXFLAGS) generators/projectgenerator.cpp - -pbuilder_pbx.o: $(SOURCE_PATH)/qmake/generators/mac/pbuilder_pbx.cpp - $(CXX) $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp - -makefiledeps.o: $(SOURCE_PATH)/qmake/generators/makefiledeps.cpp - $(CXX) $(CXXFLAGS) generators/makefiledeps.cpp - -metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp - $(CXX) $(CXXFLAGS) generators/metamakefile.cpp - -xmloutput.o: $(SOURCE_PATH)/qmake/generators/xmloutput.cpp - $(CXX) $(CXXFLAGS) generators/xmloutput.cpp - -qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp - -qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp - -qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 36c9501d5a..196fdc9540 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1136,11 +1136,7 @@ void Configure::parseCmdLine() dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32"; } else if (dictionary[ "QMAKESPEC" ] == QString("win32-g++")) { if (dictionary[ "MAKE" ].isEmpty()) dictionary[ "MAKE" ] = "mingw32-make"; - if (Environment::detectExecutable("sh.exe")) { - dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++-sh"; - } else { - dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++"; - } + dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32-g++"; } else { if (dictionary[ "MAKE" ].isEmpty()) dictionary[ "MAKE" ] = "make"; dictionary[ "QMAKEMAKEFILE" ] = "Makefile.win32"; -- cgit v1.2.3 From 5515b48ac9aa099b09285f0453fae5cdbb73f0a6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 21:01:15 +0100 Subject: use VPATH to locate sources makes the file a "tad" more concise Change-Id: I81d9721942890659ac93b32f5988f9c005c88e87 Reviewed-by: Marius Storm-Olsen --- qmake/Makefile.win32-g++ | 234 +++-------------------------------------------- 1 file changed, 11 insertions(+), 223 deletions(-) diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index d9c3b0300a..86ddcf40c7 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -6,6 +6,10 @@ ifeq "$(BUILD_PATH)" "" BUILD_PATH = .. endif +CORESRC = $(SOURCE_PATH)/src/corelib +TOOLSRC = $(SOURCE_PATH)/tools +QMKSRC = $(SOURCE_PATH)/qmake + # SHELL is the full path of sh.exe, unless # 1) it is found in the current directory # 2) it is not found at all @@ -144,227 +148,11 @@ distclean:: clean .cpp.o: $(CXX) $(CXXFLAGS) $< -qconfig.o: $(BUILD_PATH)/src/corelib/global/qconfig.cpp - $(CXX) $(CXXFLAGS) $(BUILD_PATH)/src/corelib/global/qconfig.cpp - -qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp - -qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp - -qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp - -qurl.o: $(SOURCE_PATH)/src/corelib/io/qurl.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qurl.cpp - -qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp - -qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp - -qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp - -qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp - -qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp - -qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp - -qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp - -qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qhash.cpp - -qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp - -qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp - -qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp - -qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp - -qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp - -qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp - -qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp - -qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp - -qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp - -quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp - -qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp - -qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlist.cpp - -qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp - -qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp - -qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp - -qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp - -qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp - -qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp - -qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp - -qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp - -qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp - -qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp - -qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp - -qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp - -qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp - -qvector.o: $(SOURCE_PATH)/src/corelib/tools/qvector.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvector.cpp - -qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp - -qdir.o: $(SOURCE_PATH)/src/corelib/io/qdir.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdir.cpp - -qdiriterator.o: $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp - -qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp - -qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp - -qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp - -qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp - -qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp - -qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp - -qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp - -makefile.o: $(SOURCE_PATH)/qmake/generators/makefile.cpp - $(CXX) $(CXXFLAGS) generators/makefile.cpp - -unixmake.o: $(SOURCE_PATH)/qmake/generators/unix/unixmake.cpp - $(CXX) $(CXXFLAGS) generators/unix/unixmake.cpp - -unixmake2.o: $(SOURCE_PATH)/qmake/generators/unix/unixmake2.cpp - $(CXX) $(CXXFLAGS) generators/unix/unixmake2.cpp - -winmakefile.o: $(SOURCE_PATH)/qmake/generators/win32/winmakefile.cpp - $(CXX) $(CXXFLAGS) generators/win32/winmakefile.cpp - -borland_bmake.o: $(SOURCE_PATH)/qmake/generators/win32/borland_bmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/borland_bmake.cpp - -mingw_make.o: $(SOURCE_PATH)/qmake/generators/win32/mingw_make.cpp - $(CXX) $(CXXFLAGS) generators/win32/mingw_make.cpp - -msvc_nmake.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_nmake.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_nmake.cpp - -msvc_vcproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcproj.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_vcproj.cpp - -msvc_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_objectmodel.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_objectmodel.cpp - -msvc_vcxproj.o: $(SOURCE_PATH)/qmake/generators/win32/msvc_vcxproj.cpp - $(CXX) $(CXXFLAGS) generators/win32/msvc_vcxproj.cpp - -msbuild_objectmodel.o: $(SOURCE_PATH)/qmake/generators/win32/msbuild_objectmodel.cpp - $(CXX) $(CXXFLAGS) generators/win32/msbuild_objectmodel.cpp - -registry.o: $(SOURCE_PATH)/tools/shared/windows/registry.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/tools/shared/windows/registry.cpp - -gbuild.o: $(SOURCE_PATH)/qmake/generators/integrity/gbuild.cpp - $(CXX) $(CXXFLAGS) generators/integrity/gbuild.cpp - -project.o: $(SOURCE_PATH)/qmake/project.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) project.cpp - -meta.o: $(SOURCE_PATH)/qmake/meta.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) meta.cpp - -main.o: $(SOURCE_PATH)/qmake/main.cpp $(SOURCE_PATH)/qmake/project.h - $(CXX) $(CXXFLAGS) main.cpp - -option.o: $(SOURCE_PATH)/qmake/option.cpp $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) option.cpp - -property.o: $(SOURCE_PATH)/qmake/property.cpp $(SOURCE_PATH)/qmake/project.h $(SOURCE_PATH)/qmake/option.h - $(CXX) $(CXXFLAGS) property.cpp - -projectgenerator.o: $(SOURCE_PATH)/qmake/generators/projectgenerator.cpp - $(CXX) $(CXXFLAGS) generators/projectgenerator.cpp - -pbuilder_pbx.o: $(SOURCE_PATH)/qmake/generators/mac/pbuilder_pbx.cpp - $(CXX) $(CXXFLAGS) generators/mac/pbuilder_pbx.cpp - -makefiledeps.o: $(SOURCE_PATH)/qmake/generators/makefiledeps.cpp - $(CXX) $(CXXFLAGS) generators/makefiledeps.cpp - -metamakefile.o: $(SOURCE_PATH)/qmake/generators/metamakefile.cpp - $(CXX) $(CXXFLAGS) generators/metamakefile.cpp - -xmloutput.o: $(SOURCE_PATH)/qmake/generators/xmloutput.cpp - $(CXX) $(CXXFLAGS) generators/xmloutput.cpp - -qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp - -qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp +QTVPATH = $(TOOLSRC)/shared/windows:$(CORESRC)/global:$(CORESRC)/kernel:$(CORESRC)/tools:$(CORESRC)/codecs:$(CORESRC)/io:$(CORESRC)/xml:$(CORESRC)/plugin:$(BUILD_PATH)/src/corelib/global +VPATH = $(QMKSRC):$(QMKSRC)/generators:$(QMKSRC)/generators/unix:$(QMKSRC)/generators/mac:$(QMKSRC)/generators/win32:$(QMKSRC)/generators/integrity:$(QTVPATH) -qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp - $(CXX) $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp +project.o: $(QMKSRC)/project.h $(QMKSRC)/option.h +meta.o: $(QMKSRC)/project.h $(QMKSRC)/option.h +main.o: $(QMKSRC)/project.h +option.o: $(QMKSRC)/option.h +property.o: $(QMKSRC)/project.h $(QMKSRC)/option.h -- cgit v1.2.3 From 054051d91f1e1184c58063b1dd1fb2ace3389178 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 29 Feb 2012 21:26:49 +0100 Subject: remove some bogus include locations nothing to be found in /include. neither in /src/corelib/xml. Change-Id: I381391a64542dc2ac7b421b6646c60a1b7a14639 Reviewed-by: Marius Storm-Olsen --- qmake/Makefile.unix | 2 +- qmake/Makefile.win32 | 2 -- qmake/Makefile.win32-g++ | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 16af49311b..d9835932d6 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -73,7 +73,7 @@ CPPFLAGS = -g -I. -Igenerators -Igenerators/unix -Igenerators/win32 \ -Igenerators/mac -Igenerators/integrity \ -I$(BUILD_PATH)/include -I$(BUILD_PATH)/include/QtCore \ -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION) -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION)/QtCore \ - -I$(BUILD_PATH)/src/corelib/global -I$(BUILD_PATH)/src/corelib/xml \ + -I$(BUILD_PATH)/src/corelib/global \ -I$(SOURCE_PATH)/tools/shared \ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_NO_COMPONENT -DQT_NO_STL \ diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 767237fcfc..f640216036 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -33,9 +33,7 @@ CFLAGS_BARE = -c -Fo./ \ $(CFLAGS_EXTRA) \ -I. -Igenerators -Igenerators\unix -Igenerators\win32 -Igenerators\mac -Igenerators\integrity \ -I$(BUILD_PATH)\include -I$(BUILD_PATH)\include\QtCore -I$(BUILD_PATH)\include\QtCore\$(QT_VERSION) -I$(BUILD_PATH)\include\QtCore\$(QT_VERSION)\QtCore \ - -I$(SOURCE_PATH)\include -I$(SOURCE_PATH)\include\QtCore -I$(SOURCE_PATH)\include\QtCore\$(QT_VERSION) -I$(SOURCE_PATH)\include\QtCore\$(QT_VERSION)\QtCore \ -I$(BUILD_PATH)\src\corelib\global \ - -I$(BUILD_PATH)\src\corelib\xml \ -I$(SOURCE_PATH)\mkspecs\$(QMAKESPEC) \ -I$(SOURCE_PATH)\tools\shared \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT -DQT_NODLL -DQT_NO_STL \ diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 86ddcf40c7..57e6c1aa4e 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -47,9 +47,7 @@ CFLAGS = -c -o$@ -O \ -Igenerators/win32 -Igenerators/mac \ -Igenerators/integrity \ -I$(BUILD_PATH)/include -I$(BUILD_PATH)/include/QtCore -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION) -I$(BUILD_PATH)/include/QtCore/$(QT_VERSION)/QtCore \ - -I$(SOURCE_PATH)/include -I$(SOURCE_PATH)/include/QtCore -I$(SOURCE_PATH)/include/QtCore/$(QT_VERSION) -I$(SOURCE_PATH)/include/QtCore/$(QT_VERSION)/QtCore \ -I$(BUILD_PATH)/src/corelib/global \ - -I$(BUILD_PATH)/src/corelib/xml \ -I$(SOURCE_PATH)/mkspecs/win32-g++ \ -I$(SOURCE_PATH)/tools/shared \ -DQT_NO_TEXTCODEC -DQT_NO_UNICODETABLES -DQT_LITE_COMPONENT \ -- cgit v1.2.3 From c3a1af63ae8a7475d093fe4372d86360cebfa541 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Feb 2012 17:30:58 +0100 Subject: search for default spec just like for other ones that way qtbase will find its spec without hacking .qmake.cache. note that passing "-spec default" on the command line would have already triggered the normal path, so artificial limitation did not even provide safety against abuse (it is arguably pointless/counterproductive for other projects than qtbase to have a default spec). Change-Id: Ib0c3e6498fd70cd6f9561951d72a47165878bb33 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 6793ed3be6..2d339ccb63 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1291,26 +1291,12 @@ QMakeProject::read(uchar cmd) } if (cmd & ReadSetup) { // parse mkspec QString qmakespec = fixEnvVariables(Option::mkfile::qmakespec); - QStringList mkspec_roots = qmake_mkspec_paths(); - debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), - mkspec_roots.join("::").toLatin1().constData()); - if(qmakespec.isEmpty()) { - for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { - QString mkspec = (*it) + QLatin1String("/default"); - QFileInfo default_info(mkspec); - if(default_info.exists() && default_info.isDir()) { - qmakespec = mkspec; - break; - } - } - if(qmakespec.isEmpty()) { - fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); - return false; - } - Option::mkfile::qmakespec = qmakespec; - } - + if (qmakespec.isEmpty()) + qmakespec = "default"; if(QDir::isRelativePath(qmakespec)) { + QStringList mkspec_roots = qmake_mkspec_paths(); + debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), + mkspec_roots.join("::").toLatin1().constData()); bool found_mkspec = false; for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QLatin1Char('/') + qmakespec; -- cgit v1.2.3 From 88374c79634469b0162bbaac108a360cfc3e3b7b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 1 Mar 2012 09:59:33 +0200 Subject: Add protocol type B support to the evdevtouch plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also adds optional support for libmtdev (a helper library which translates transparently from type A to B when using type A kernel drivers). Change-Id: Ic9c065b2fd130e9db2dd07e7dc103e9d45c08c99 Reviewed-by: Samuel Rødal --- src/plugins/generic/evdevtouch/README | 12 +++- src/plugins/generic/evdevtouch/evdevtouch.pro | 4 ++ src/plugins/generic/evdevtouch/qevdevtouch.cpp | 89 ++++++++++++++++++++++++-- src/plugins/generic/evdevtouch/qevdevtouch.h | 8 ++- 4 files changed, 102 insertions(+), 11 deletions(-) diff --git a/src/plugins/generic/evdevtouch/README b/src/plugins/generic/evdevtouch/README index 4764ef8f70..119f2a2c9e 100644 --- a/src/plugins/generic/evdevtouch/README +++ b/src/plugins/generic/evdevtouch/README @@ -1,8 +1,14 @@ -Generic plug-in for evdev touch events. (protocol type A) +Generic plug-in for evdev touch (ABS_MT) events. +Supports protocol type A & B. +Type B is supported both directly and via libmtdev. -Tested with the following drivers: bcm5974, hid_magicmouse. +The protocol type will be detected automatically. +To enable libmtdev support uncomment the USE_MTDEV define in +evdevtouch.pro. -To use it, pass -plugin EvdevTouch on the command line. +Tested with the following kernel drivers: bcm5974, hid_magicmouse. + +To use this "driver", pass -plugin EvdevTouch on the command line. If automatic detection does not work, use -plugin EvdevTouch:/dev/input/eventN to explicitly set the device file diff --git a/src/plugins/generic/evdevtouch/evdevtouch.pro b/src/plugins/generic/evdevtouch/evdevtouch.pro index 284f1d1221..f9fb4a61d8 100644 --- a/src/plugins/generic/evdevtouch/evdevtouch.pro +++ b/src/plugins/generic/evdevtouch/evdevtouch.pro @@ -15,3 +15,7 @@ QT += core-private platformsupport-private OTHER_FILES += \ evdevtouch.json + +# DEFINES += USE_MTDEV + +contains(DEFINES, USE_MTDEV): LIBS += -lmtdev diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp index d508c4a12a..73f253ae96 100644 --- a/src/plugins/generic/evdevtouch/qevdevtouch.cpp +++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp @@ -49,8 +49,18 @@ #include #include +#ifdef USE_MTDEV +extern "C" { +#include +} +#endif + QT_BEGIN_NAMESPACE +#ifndef ABS_MT_SLOT +#define ABS_MT_SLOT 0x2f +#endif + class QTouchScreenData { public: @@ -75,8 +85,10 @@ public: x(0), y(0), maj(1), pressure(0), state(Qt::TouchPointPressed), flags(0) { } }; - QHash m_contacts, m_lastContacts; + QHash m_contacts; // The key is a tracking id for type A, slot number for type B. + QHash m_lastContacts; Contact m_currentData; + int m_currentSlot; int findClosestContact(const QHash &contacts, int x, int y, int *dist); void reportPoints(); @@ -91,11 +103,13 @@ public: QString hw_name; bool m_forceToActiveWindow; QTouchDevice *m_device; + bool m_typeB; }; QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args) : q(q_ptr), m_lastEventType(-1), + m_currentSlot(0), hw_range_x_min(0), hw_range_x_max(0), hw_range_y_min(0), hw_range_y_max(0), hw_pressure_min(0), hw_pressure_max(0) @@ -115,8 +129,19 @@ void QTouchScreenData::registerDevice() QWindowSystemInterface::registerTouchDevice(m_device); } +#define LONG_BITS (sizeof(long) << 3) +#define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS) + +static inline bool testBit(long bit, const long *array) +{ + return array[bit / LONG_BITS] & (1 << (bit & (LONG_BITS - 1))); +} + QTouchScreenHandler::QTouchScreenHandler(const QString &spec) : m_notify(0), m_fd(-1), d(0) +#ifdef USE_MTDEV + , m_mtdev(0) +#endif { setObjectName(QLatin1String("Evdev Touch Handler")); @@ -141,6 +166,16 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec) return; } +#ifdef USE_MTDEV + m_mtdev = static_cast(calloc(1, sizeof(mtdev))); + int mtdeverr = mtdev_open(m_mtdev, m_fd); + if (mtdeverr) { + qWarning("mtdev_open failed: %d", mtdeverr); + QT_CLOSE(m_fd); + return; + } +#endif + d = new QTouchScreenData(this, args); input_absinfo absInfo; @@ -168,11 +203,30 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec) qDebug("device name: %s", name); } +#ifdef USE_MTDEV + const char *mtdevStr = "(mtdev)"; + d->m_typeB = true; +#else + const char *mtdevStr = ""; + d->m_typeB = false; + long absbits[NUM_LONGS(ABS_CNT)]; + if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits) >= 0) + d->m_typeB = testBit(ABS_MT_SLOT, absbits); +#endif + qDebug("Protocol type %c %s", d->m_typeB ? 'B' : 'A', mtdevStr); + d->registerDevice(); } QTouchScreenHandler::~QTouchScreenHandler() { +#ifdef USE_MTDEV + if (m_mtdev) { + mtdev_close(m_mtdev); + free(m_mtdev); + } +#endif + if (m_fd >= 0) QT_CLOSE(m_fd); @@ -184,8 +238,13 @@ void QTouchScreenHandler::readData() ::input_event buffer[32]; int n = 0; for (; ;) { +#ifdef USE_MTDEV + n = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event)); + if (n > 0) + n *= sizeof(::input_event); +#else n = QT_READ(m_fd, reinterpret_cast(buffer) + n, sizeof(buffer) - n); - +#endif if (!n) { qWarning("Got EOF from input device"); return; @@ -215,16 +274,32 @@ void QTouchScreenData::processInputEvent(input_event *data) if (data->code == ABS_MT_POSITION_X) { m_currentData.x = qBound(hw_range_x_min, data->value, hw_range_x_max); + if (m_typeB) + m_contacts[m_currentSlot].x = m_currentData.x; } else if (data->code == ABS_MT_POSITION_Y) { m_currentData.y = qBound(hw_range_y_min, data->value, hw_range_y_max); + if (m_typeB) + m_contacts[m_currentSlot].y = m_currentData.y; } else if (data->code == ABS_MT_TRACKING_ID) { m_currentData.trackingId = data->value; + if (m_typeB) { + if (m_currentData.trackingId == -1) + m_contacts[m_currentSlot].state = Qt::TouchPointReleased; + else + m_contacts[m_currentSlot].trackingId = m_currentData.trackingId; + } } else if (data->code == ABS_MT_TOUCH_MAJOR) { m_currentData.maj = data->value; if (data->value == 0) m_currentData.state = Qt::TouchPointReleased; + if (m_typeB) + m_contacts[m_currentSlot].maj = m_currentData.maj; } else if (data->code == ABS_PRESSURE) { m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max); + if (m_typeB) + m_contacts[m_currentSlot].pressure = m_currentData.pressure; + } else if (data->code == ABS_MT_SLOT) { + m_currentSlot = data->value; } } else if (data->type == EV_SYN && data->code == SYN_MT_REPORT && m_lastEventType != EV_SYN) { @@ -254,8 +329,9 @@ void QTouchScreenData::processInputEvent(input_event *data) tp.id = contact.trackingId; tp.flags = contact.flags; - if (m_lastContacts.contains(contact.trackingId)) { - const Contact &prev(m_lastContacts.value(contact.trackingId)); + int key = m_typeB ? it.key() : contact.trackingId; + if (m_lastContacts.contains(key)) { + const Contact &prev(m_lastContacts.value(key)); if (contact.state == Qt::TouchPointReleased) { // Copy over the previous values for released points, just in case. contact.x = prev.x; @@ -269,7 +345,7 @@ void QTouchScreenData::processInputEvent(input_event *data) // Avoid reporting a contact in released state more than once. if (contact.state == Qt::TouchPointReleased - && !m_lastContacts.contains(contact.trackingId)) { + && !m_lastContacts.contains(key)) { it.remove(); continue; } @@ -293,7 +369,8 @@ void QTouchScreenData::processInputEvent(input_event *data) } m_lastContacts = m_contacts; - m_contacts.clear(); + if (!m_typeB) + m_contacts.clear(); if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary) reportPoints(); diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.h b/src/plugins/generic/evdevtouch/qevdevtouch.h index 343f638526..28a3b215fb 100644 --- a/src/plugins/generic/evdevtouch/qevdevtouch.h +++ b/src/plugins/generic/evdevtouch/qevdevtouch.h @@ -54,6 +54,9 @@ QT_BEGIN_NAMESPACE class QSocketNotifier; class QTouchScreenData; +#ifdef USE_MTDEV +struct mtdev; +#endif class QTouchScreenHandler : public QObject { @@ -67,11 +70,12 @@ private slots: void readData(); private: - void pathFromUdev(QString *path); - QSocketNotifier *m_notify; int m_fd; QTouchScreenData *d; +#ifdef USE_MTDEV + mtdev *m_mtdev; +#endif }; class QTouchScreenHandlerThread : public QThread -- cgit v1.2.3 From 51296085b9d96b131d1f095dd2cfe61745c07ef3 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Wed, 29 Feb 2012 12:49:25 +1000 Subject: testlib: Improve documentation of verbose test logging options. Change the help output to show which options only work for plain text logging. Change-Id: I39eb7cd0793cdbe553c230334c6cd532b4929f61 Reviewed-by: Rohan McGovern --- src/testlib/qtestcase.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index a4f1a39bbd..e16787693d 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1191,11 +1191,13 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, char *argv[], bool qml) " *** If no output file is specified, stdout is assumed.\n" " *** If no output format is specified, -txt is assumed.\n" "\n" - " Detail options:\n" - " -silent : Only output failures and fatal errors in plain text output\n" - " -v1 : Print enter messages for each testfunction\n" - " -v2 : Also print out each QVERIFY/QCOMPARE/QTEST\n" - " -vs : Print every signal emitted\n" + " Test log detail options:\n" + " -silent : Log failures and fatal errors only\n" + " -v1 : Log the start of each testfunction\n" + " -v2 : Log each QVERIFY/QCOMPARE/QTEST (implies -v1)\n" + " -vs : Log every signal emission and resulting slot invocations\n" + "\n" + " *** The -silent and -v1 options only affect plain text output.\n" "\n" " Testing options:\n" " -functions : Returns a list of current testfunctions\n" -- cgit v1.2.3 From 123eb803ef1a7af36eefdf9a668f1f29d6597f1d Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Thu, 1 Mar 2012 11:01:49 +1000 Subject: testlib: Add selftests for -v1 and -v2 command-line switches. These tests don't have their own source code but rather reuse the counting selftest with additional command-line options. Note that currently the -v1 switch only changes the plain text output, and the expected xml output is identical to that of the counting test. This may change in the future however. This commit also restores a couple of lists to alphabetical order, where the findtestdata selftest was not sorted into the list correctly. Change-Id: Ie38e255f8029157b34162b3864b5fa66e137d74a Reviewed-by: Rohan McGovern --- .../testlib/selftests/expected_verbose1.lightxml | 150 +++++++++++++++ tests/auto/testlib/selftests/expected_verbose1.txt | 69 +++++++ tests/auto/testlib/selftests/expected_verbose1.xml | 153 ++++++++++++++++ .../testlib/selftests/expected_verbose1.xunitxml | 64 +++++++ .../testlib/selftests/expected_verbose2.lightxml | 198 ++++++++++++++++++++ tests/auto/testlib/selftests/expected_verbose2.txt | 93 ++++++++++ tests/auto/testlib/selftests/expected_verbose2.xml | 201 +++++++++++++++++++++ .../testlib/selftests/expected_verbose2.xunitxml | 89 +++++++++ tests/auto/testlib/selftests/selftests.pri | 2 + tests/auto/testlib/selftests/selftests.qrc | 16 +- tests/auto/testlib/selftests/tst_selftests.cpp | 10 +- tests/auto/testlib/selftests/verbose1/verbose1.pro | 10 + tests/auto/testlib/selftests/verbose2/verbose2.pro | 10 + 13 files changed, 1060 insertions(+), 5 deletions(-) create mode 100644 tests/auto/testlib/selftests/expected_verbose1.lightxml create mode 100644 tests/auto/testlib/selftests/expected_verbose1.txt create mode 100644 tests/auto/testlib/selftests/expected_verbose1.xml create mode 100644 tests/auto/testlib/selftests/expected_verbose1.xunitxml create mode 100644 tests/auto/testlib/selftests/expected_verbose2.lightxml create mode 100644 tests/auto/testlib/selftests/expected_verbose2.txt create mode 100644 tests/auto/testlib/selftests/expected_verbose2.xml create mode 100644 tests/auto/testlib/selftests/expected_verbose2.xunitxml create mode 100644 tests/auto/testlib/selftests/verbose1/verbose1.pro create mode 100644 tests/auto/testlib/selftests/verbose2/verbose2.pro diff --git a/tests/auto/testlib/selftests/expected_verbose1.lightxml b/tests/auto/testlib/selftests/expected_verbose1.lightxml new file mode 100644 index 0000000000..e7b1136417 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose1.lightxml @@ -0,0 +1,150 @@ + + @INSERT_QT_VERSION_HERE@ + @INSERT_QT_VERSION_HERE@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_verbose1.txt b/tests/auto/testlib/selftests/expected_verbose1.txt new file mode 100644 index 0000000000..4a0fec51ae --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose1.txt @@ -0,0 +1,69 @@ +********* Start testing of tst_Counting ********* +Config: Using QTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@ +INFO : tst_Counting::initTestCase() entering +PASS : tst_Counting::initTestCase() +INFO : tst_Counting::testPassPass() entering +PASS : tst_Counting::testPassPass(row 1) +PASS : tst_Counting::testPassPass(row 2) +INFO : tst_Counting::testPassSkip() entering +PASS : tst_Counting::testPassSkip(row 1) +SKIP : tst_Counting::testPassSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testPassFail() entering +PASS : tst_Counting::testPassFail(row 1) +FAIL! : tst_Counting::testPassFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testSkipPass() entering +SKIP : tst_Counting::testSkipPass(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +PASS : tst_Counting::testSkipPass(row 2) +INFO : tst_Counting::testSkipSkip() entering +SKIP : tst_Counting::testSkipSkip(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +SKIP : tst_Counting::testSkipSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testSkipFail() entering +SKIP : tst_Counting::testSkipFail(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +FAIL! : tst_Counting::testSkipFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailPass() entering +FAIL! : tst_Counting::testFailPass(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +PASS : tst_Counting::testFailPass(row 2) +INFO : tst_Counting::testFailSkip() entering +FAIL! : tst_Counting::testFailSkip(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +SKIP : tst_Counting::testFailSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testFailFail() entering +FAIL! : tst_Counting::testFailFail(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testFailFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailInInit() entering +PASS : tst_Counting::testFailInInit(before) +FAIL! : tst_Counting::testFailInInit(fail) Fail in init() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(233)] +PASS : tst_Counting::testFailInInit(after) +INFO : tst_Counting::testFailInCleanup() entering +PASS : tst_Counting::testFailInCleanup(before) +QDEBUG : tst_Counting::testFailInCleanup(fail) This test function should execute and then QFAIL in cleanup() +FAIL! : tst_Counting::testFailInCleanup(fail) Fail in cleanup() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(241)] +PASS : tst_Counting::testFailInCleanup(after) +INFO : tst_Counting::testSkipInInit() entering +PASS : tst_Counting::testSkipInInit(before) +SKIP : tst_Counting::testSkipInInit(skip) Skip in init() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(235)] +PASS : tst_Counting::testSkipInInit(after) +INFO : tst_Counting::testSkipInCleanup() entering +PASS : tst_Counting::testSkipInCleanup(before) +QDEBUG : tst_Counting::testSkipInCleanup(skip) This test function should execute and then QSKIP in cleanup() +SKIP : tst_Counting::testSkipInCleanup(skip) Skip in cleanup() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(243)] +PASS : tst_Counting::testSkipInCleanup(after) +INFO : tst_Counting::cleanupTestCase() entering +PASS : tst_Counting::cleanupTestCase() +Totals: 16 passed, 8 failed, 8 skipped +********* Finished testing of tst_Counting ********* diff --git a/tests/auto/testlib/selftests/expected_verbose1.xml b/tests/auto/testlib/selftests/expected_verbose1.xml new file mode 100644 index 0000000000..a97296807d --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose1.xml @@ -0,0 +1,153 @@ + + + + @INSERT_QT_VERSION_HERE@ + @INSERT_QT_VERSION_HERE@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_verbose1.xunitxml b/tests/auto/testlib/selftests/expected_verbose1.xunitxml new file mode 100644 index 0000000000..f317ed5923 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose1.xunitxml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_verbose2.lightxml b/tests/auto/testlib/selftests/expected_verbose2.lightxml new file mode 100644 index 0000000000..b2d9607ade --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose2.lightxml @@ -0,0 +1,198 @@ + + @INSERT_QT_VERSION_HERE@ + @INSERT_QT_VERSION_HERE@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_verbose2.txt b/tests/auto/testlib/selftests/expected_verbose2.txt new file mode 100644 index 0000000000..9d36a5e98e --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose2.txt @@ -0,0 +1,93 @@ +********* Start testing of tst_Counting ********* +Config: Using QTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@ +INFO : tst_Counting::initTestCase() entering +PASS : tst_Counting::initTestCase() +INFO : tst_Counting::testPassPass() entering +INFO : tst_Counting::testPassPass(row 1) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testPassPass(row 1) +INFO : tst_Counting::testPassPass(row 2) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testPassPass(row 2) +INFO : tst_Counting::testPassSkip() entering +INFO : tst_Counting::testPassSkip(row 1) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testPassSkip(row 1) +SKIP : tst_Counting::testPassSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testPassFail() entering +INFO : tst_Counting::testPassFail(row 1) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testPassFail(row 1) +INFO : tst_Counting::testPassFail(row 2) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testPassFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testSkipPass() entering +SKIP : tst_Counting::testSkipPass(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testSkipPass(row 2) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testSkipPass(row 2) +INFO : tst_Counting::testSkipSkip() entering +SKIP : tst_Counting::testSkipSkip(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +SKIP : tst_Counting::testSkipSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testSkipFail() entering +SKIP : tst_Counting::testSkipFail(row 1) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testSkipFail(row 2) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testSkipFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailPass() entering +INFO : tst_Counting::testFailPass(row 1) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testFailPass(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailPass(row 2) QVERIFY(true) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +PASS : tst_Counting::testFailPass(row 2) +INFO : tst_Counting::testFailSkip() entering +INFO : tst_Counting::testFailSkip(row 1) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testFailSkip(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +SKIP : tst_Counting::testFailSkip(row 2) Skipping + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] +INFO : tst_Counting::testFailFail() entering +INFO : tst_Counting::testFailFail(row 1) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testFailFail(row 1) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailFail(row 2) QVERIFY(false) + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +FAIL! : tst_Counting::testFailFail(row 2) 'false' returned FALSE. () + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] +INFO : tst_Counting::testFailInInit() entering +PASS : tst_Counting::testFailInInit(before) +FAIL! : tst_Counting::testFailInInit(fail) Fail in init() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(233)] +PASS : tst_Counting::testFailInInit(after) +INFO : tst_Counting::testFailInCleanup() entering +PASS : tst_Counting::testFailInCleanup(before) +QDEBUG : tst_Counting::testFailInCleanup(fail) This test function should execute and then QFAIL in cleanup() +FAIL! : tst_Counting::testFailInCleanup(fail) Fail in cleanup() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(241)] +PASS : tst_Counting::testFailInCleanup(after) +INFO : tst_Counting::testSkipInInit() entering +PASS : tst_Counting::testSkipInInit(before) +SKIP : tst_Counting::testSkipInInit(skip) Skip in init() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(235)] +PASS : tst_Counting::testSkipInInit(after) +INFO : tst_Counting::testSkipInCleanup() entering +PASS : tst_Counting::testSkipInCleanup(before) +QDEBUG : tst_Counting::testSkipInCleanup(skip) This test function should execute and then QSKIP in cleanup() +SKIP : tst_Counting::testSkipInCleanup(skip) Skip in cleanup() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(243)] +PASS : tst_Counting::testSkipInCleanup(after) +INFO : tst_Counting::cleanupTestCase() entering +PASS : tst_Counting::cleanupTestCase() +Totals: 16 passed, 8 failed, 8 skipped +********* Finished testing of tst_Counting ********* diff --git a/tests/auto/testlib/selftests/expected_verbose2.xml b/tests/auto/testlib/selftests/expected_verbose2.xml new file mode 100644 index 0000000000..90582e6116 --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose2.xml @@ -0,0 +1,201 @@ + + + + @INSERT_QT_VERSION_HERE@ + @INSERT_QT_VERSION_HERE@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_verbose2.xunitxml b/tests/auto/testlib/selftests/expected_verbose2.xunitxml new file mode 100644 index 0000000000..558550f17b --- /dev/null +++ b/tests/auto/testlib/selftests/expected_verbose2.xunitxml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri index 1fc66e6364..c9474419eb 100644 --- a/tests/auto/testlib/selftests/selftests.pri +++ b/tests/auto/testlib/selftests/selftests.pri @@ -39,5 +39,7 @@ SUBPROGRAMS = \ sleep \ strcmp \ subtest \ + verbose1 \ + verbose2 \ warnings \ xunit diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc index e39515e5be..03de05fb89 100644 --- a/tests/auto/testlib/selftests/selftests.qrc +++ b/tests/auto/testlib/selftests/selftests.qrc @@ -75,6 +75,10 @@ expected_fetchbogus.txt expected_fetchbogus.xml expected_fetchbogus.xunitxml + expected_findtestdata.lightxml + expected_findtestdata.txt + expected_findtestdata.xml + expected_findtestdata.xunitxml expected_float.txt expected_globaldata.lightxml expected_globaldata.txt @@ -122,10 +126,14 @@ expected_subtest.txt expected_subtest.xml expected_subtest.xunitxml - expected_findtestdata.lightxml - expected_findtestdata.txt - expected_findtestdata.xml - expected_findtestdata.xunitxml + expected_verbose1.lightxml + expected_verbose1.txt + expected_verbose1.xml + expected_verbose1.xunitxml + expected_verbose2.lightxml + expected_verbose2.txt + expected_verbose2.xml + expected_verbose2.xunitxml expected_warnings.lightxml expected_warnings.txt expected_warnings.xml diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 2b90bdb389..5d216992d7 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -346,6 +346,7 @@ void tst_Selftests::runSubTest_data() // Disable this test on Windows, as the run-time will popup dialogs with warnings << "fetchbogus" #endif + << "findtestdata" << "float" << "globaldata" << "longstring" @@ -363,7 +364,8 @@ void tst_Selftests::runSubTest_data() << "sleep" << "strcmp" << "subtest" - << "findtestdata" + << "verbose1" + << "verbose2" << "warnings" << "xunit" ; @@ -413,6 +415,12 @@ void tst_Selftests::runSubTest_data() else if (subtest == "silent") { arguments << "-silent"; } + else if (subtest == "verbose1") { + arguments << "-v1"; + } + else if (subtest == "verbose2") { + arguments << "-v2"; + } // These tests don't work right unless logging plain text to diff --git a/tests/auto/testlib/selftests/verbose1/verbose1.pro b/tests/auto/testlib/selftests/verbose1/verbose1.pro new file mode 100644 index 0000000000..f00ae69d17 --- /dev/null +++ b/tests/auto/testlib/selftests/verbose1/verbose1.pro @@ -0,0 +1,10 @@ +# This test just reuses the counting selftest to show how the output +# differs when the -v1 command-line switch is used. + +SOURCES += ../counting/tst_counting.cpp +QT = core testlib + +mac:CONFIG -= app_bundle +CONFIG -= debug_and_release_target + +TARGET = verbose1 diff --git a/tests/auto/testlib/selftests/verbose2/verbose2.pro b/tests/auto/testlib/selftests/verbose2/verbose2.pro new file mode 100644 index 0000000000..796cdeb975 --- /dev/null +++ b/tests/auto/testlib/selftests/verbose2/verbose2.pro @@ -0,0 +1,10 @@ +# This test just reuses the counting selftest to show how the output +# differs when the -v2 command-line switch is used. + +SOURCES += ../counting/tst_counting.cpp +QT = core testlib + +mac:CONFIG -= app_bundle +CONFIG -= debug_and_release_target + +TARGET = verbose2 -- cgit v1.2.3 From 74a6669fa7c0d6e2cb7d34d56332d620d2a07755 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 23 Feb 2012 19:34:10 +0100 Subject: move finding the makespec to Option this is a one-time operation which depends only on the invocation, so this new home is much more appropriate. Change-Id: I07c66d95a9ae01a664cec17564995311fb78ec9b Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/option.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ qmake/option.h | 2 ++ qmake/project.cpp | 43 +------------------------------------------ qmake/property.cpp | 4 +--- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/qmake/option.cpp b/qmake/option.cpp index 16c5390348..93a0ffbd9c 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -577,6 +577,47 @@ void Option::applyHostMode() } } +QStringList Option::mkspecPaths() +{ + QStringList ret; + const QString concat = QLatin1String("/mkspecs"); + + QByteArray qmakepath = qgetenv("QMAKEPATH"); + if (!qmakepath.isEmpty()) { + const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); + for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) + ret << ((*it) + concat); + } + ret << Option::mkfile::project_build_root + concat; + if (!Option::mkfile::project_root.isEmpty()) + ret << Option::mkfile::project_root + concat; + ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; + return ret; +} + +bool Option::resolveSpec(QString *spec) +{ + QString qmakespec = fixEnvVariables(*spec); + if (qmakespec.isEmpty()) + qmakespec = "default"; + if (QDir::isRelativePath(qmakespec)) { + QStringList mkspec_roots = mkspecPaths(); + debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), + mkspec_roots.join("::").toLatin1().constData()); + for (QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { + QString mkspec = (*it) + QLatin1Char('/') + qmakespec; + if (QFile::exists(mkspec)) { + *spec = mkspec; + return true; + } + } + fprintf(stderr, "Could not find mkspecs for your QMAKESPEC(%s) after trying:\n\t%s\n", + qmakespec.toLatin1().constData(), mkspec_roots.join("\n\t").toLatin1().constData()); + return false; + } + return true; +} + bool Option::prepareProject(const QString &pfile) { mkfile::project_build_root.clear(); @@ -630,6 +671,9 @@ bool Option::prepareProject(const QString &pfile) mkfile::project_root.clear(); } + if (!resolveSpec(&Option::mkfile::qmakespec)) + return false; + return true; } diff --git a/qmake/option.h b/qmake/option.h index a4d8cccbec..96549bb5bc 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -108,6 +108,7 @@ struct Option //both of these must be called.. static int init(int argc=0, char **argv=0); //parse cmdline static void applyHostMode(); + static QStringList mkspecPaths(); static bool prepareProject(const QString &pfile); static bool postProcessProject(QMakeProject *); @@ -212,6 +213,7 @@ struct Option private: static int parseCommandLine(int, char **, int=0); + static bool resolveSpec(QString *spec); }; inline QString fixEnvVariables(const QString &x) { return Option::fixString(x, Option::FixEnvVars); } diff --git a/qmake/project.cpp b/qmake/project.cpp index 2d339ccb63..0533ab30b5 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -596,24 +596,6 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) return feature_roots; } -QStringList qmake_mkspec_paths() -{ - QStringList ret; - const QString concat = QLatin1String("/mkspecs"); - QByteArray qmakepath = qgetenv("QMAKEPATH"); - if (!qmakepath.isEmpty()) { - const QStringList lst = splitPathList(QString::fromLocal8Bit(qmakepath)); - for(QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) - ret << ((*it) + concat); - } - ret << Option::mkfile::project_build_root + concat; - if (!Option::mkfile::project_root.isEmpty()) - ret << Option::mkfile::project_root + concat; - ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat; - - return ret; -} - QMakeProject::~QMakeProject() { if(own_prop) @@ -1290,30 +1272,7 @@ QMakeProject::read(uchar cmd) Option::output_dir.mid(Option::mkfile::project_build_root.length()).count('/'); } if (cmd & ReadSetup) { // parse mkspec - QString qmakespec = fixEnvVariables(Option::mkfile::qmakespec); - if (qmakespec.isEmpty()) - qmakespec = "default"; - if(QDir::isRelativePath(qmakespec)) { - QStringList mkspec_roots = qmake_mkspec_paths(); - debug_msg(2, "Looking for mkspec %s in (%s)", qmakespec.toLatin1().constData(), - mkspec_roots.join("::").toLatin1().constData()); - bool found_mkspec = false; - for(QStringList::ConstIterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { - QString mkspec = (*it) + QLatin1Char('/') + qmakespec; - if(QFile::exists(mkspec)) { - found_mkspec = true; - Option::mkfile::qmakespec = qmakespec = mkspec; - break; - } - } - if(!found_mkspec) { - fprintf(stderr, "Could not find mkspecs for your QMAKESPEC(%s) after trying:\n\t%s\n", - qmakespec.toLatin1().constData(), mkspec_roots.join("\n\t").toLatin1().constData()); - return false; - } - } - - // parse qmake configuration + QString qmakespec = Option::mkfile::qmakespec; while(qmakespec.endsWith(QLatin1Char('/'))) qmakespec.truncate(qmakespec.length()-1); QString spec = qmakespec + QLatin1String("/qmake.conf"); diff --git a/qmake/property.cpp b/qmake/property.cpp index 4221605545..064c8f6082 100644 --- a/qmake/property.cpp +++ b/qmake/property.cpp @@ -49,8 +49,6 @@ QT_BEGIN_NAMESPACE -QStringList qmake_mkspec_paths(); //project.cpp - QMakeProperty::QMakeProperty() : settings(0) { } @@ -107,7 +105,7 @@ QMakeProperty::value(QString v, bool just_check) else if(v == "QT_INSTALL_DEMOS") return QLibraryInfo::location(QLibraryInfo::ExamplesPath); else if(v == "QMAKE_MKSPECS") - return qmake_mkspec_paths().join(Option::dirlist_sep); + return Option::mkspecPaths().join(Option::dirlist_sep); else if(v == "QMAKE_VERSION") return qmake_version(); #ifdef QT_VERSION_STR -- cgit v1.2.3 From 93ee903da7b10326b40bc43d5f5c659d527e8814 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 21 Feb 2012 12:44:27 +0100 Subject: clean up build pass project initialization instead of messing with the Option singleton, add a way to inject extra config values into QMakeProject. Change-Id: Ia347dcc38af2c72913e30ebf5c2b4044f93b4f5f Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/generators/metamakefile.cpp | 16 ++++++---------- qmake/option.cpp | 1 - qmake/option.h | 2 +- qmake/project.cpp | 18 ++++++++++++++---- qmake/project.h | 3 +++ 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index b9fec023ab..55ab0a5af5 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -238,25 +238,21 @@ MakefileGenerator //initialize the base QHash basevars; + QStringList basecfgs; if(!project->isEmpty(build + ".CONFIG")) - basevars["CONFIG"] += project->values(build + ".CONFIG"); - basevars["CONFIG"] += build; - basevars["CONFIG"] += "build_pass"; + basecfgs = project->values(build + ".CONFIG"); + basecfgs += build; + basecfgs += "build_pass"; + basevars["CONFIG"] = basecfgs; basevars["BUILD_PASS"] = QStringList(build); QStringList buildname = project->values(build + ".name"); basevars["BUILD_NAME"] = (buildname.isEmpty() ? QStringList(build) : buildname); //create project QMakeProject *build_proj = new QMakeProject(project->properties(), basevars); + build_proj->setExtraConfigs(basecfgs); - //all the user configs must be set again afterwards (for .pro tests and for .prf tests) - const QStringList old_after_user_config = Option::after_user_configs; - const QStringList old_user_config = Option::user_configs; - Option::after_user_configs += basevars["CONFIG"]; - Option::user_configs += basevars["CONFIG"]; build_proj->read(project->projectFile()); - Option::after_user_configs = old_after_user_config; - Option::user_configs = old_user_config; //done return createMakefileGenerator(build_proj); diff --git a/qmake/option.cpp b/qmake/option.cpp index 93a0ffbd9c..c73eb149ec 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -92,7 +92,6 @@ Option::QMAKE_RECURSIVE Option::recursive = Option::QMAKE_RECURSIVE_DEFAULT; QStringList Option::before_user_vars; QStringList Option::after_user_vars; QStringList Option::user_configs; -QStringList Option::after_user_configs; QString Option::user_template; QString Option::user_template_prefix; QStringList Option::shellPath; diff --git a/qmake/option.h b/qmake/option.h index 96549bb5bc..d1bfcd169b 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -173,7 +173,7 @@ struct Option static int warn_level; enum QMAKE_RECURSIVE { QMAKE_RECURSIVE_DEFAULT, QMAKE_RECURSIVE_YES, QMAKE_RECURSIVE_NO }; static QMAKE_RECURSIVE recursive; - static QStringList before_user_vars, after_user_vars, user_configs, after_user_configs; + static QStringList before_user_vars, after_user_vars, user_configs; enum HOST_MODE { HOST_UNKNOWN_MODE, HOST_UNIX_MODE, HOST_WIN_MODE, HOST_MACX_MODE }; static HOST_MODE host_mode; enum TARG_MODE { TARG_UNKNOWN_MODE, TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, diff --git a/qmake/project.cpp b/qmake/project.cpp index 0533ab30b5..8aa3ed2ed6 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1326,6 +1326,14 @@ QMakeProject::read(uchar cmd) parse("CONFIG += " + Option::user_configs.join(" "), vars); } + // After user configs, to override them + if (!extra_configs.isEmpty()) { + parser.file = "(extra configs)"; + parser.from_file = false; + parser.line_no = 1; //really arg count now.. duh + parse("CONFIG += " + extra_configs.join(" "), vars); + } + if(cmd & ReadProFile) { // parse project file debug_msg(1, "Project file: reading %s", pfile.toLatin1().constData()); if(pfile != "-" && !QFile::exists(pfile) && !pfile.endsWith(Option::pro_ext)) @@ -1349,12 +1357,14 @@ QMakeProject::read(uchar cmd) } } - //after configs (set in BUILDS) - if ((cmd & ReadSetup) && !Option::after_user_configs.isEmpty()) { - parser.file = "(configs)"; + // Again, to ensure the project does not mess with us. + // Specifically, do not allow a project to override debug/release within a + // debug_and_release build pass - it's too late for that at this point anyway. + if (!extra_configs.isEmpty()) { + parser.file = "(extra configs)"; parser.from_file = false; parser.line_no = 1; //really arg count now.. duh - parse("CONFIG += " + Option::after_user_configs.join(" "), vars); + parse("CONFIG += " + extra_configs.join(" "), vars); } if(cmd & ReadFeatures) { diff --git a/qmake/project.h b/qmake/project.h index ce90be035f..43623a3974 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -84,6 +84,7 @@ class QMakeProject QString pfile, cfile; QMakeProperty *prop; void reset(); + QStringList extra_configs; QHash vars, base_vars; bool parse(const QString &text, QHash &place, int line_count=1); @@ -118,6 +119,8 @@ public: QMakeProject(QMakeProperty *p, const QHash &nvars) { init(p, &nvars); } ~QMakeProject(); + void setExtraConfigs(const QStringList &_cfgs) { extra_configs = _cfgs; } + enum { ReadProFile=0x01, ReadSetup=0x02, ReadFeatures=0x04, ReadAll=0xFF }; inline bool parse(const QString &text) { return parse(text, vars); } bool read(const QString &project, uchar cmd=ReadAll); -- cgit v1.2.3 From d505886dd696d0f01bb64cbc7a1191d960d4d060 Mon Sep 17 00:00:00 2001 From: Rick Stockton Date: Wed, 29 Feb 2012 23:56:34 -0800 Subject: Support 16+4 mouse buttons within the generic/evdevmouse plugin. The Kernel's evdev module is capable of presenting up to 16 mouse buttons, plus wheel events (UP, DOWN, LEFT, and RIGHT). This patch updates our Plugin, so that it tranlates all of those button numbers into corresponding MouseEvent Qt::MouseButton values. Task-number: QTBUG-24590 Change-Id: Ib8cbb9500280c76f06a51ce95095e22ae84de1c6 Reviewed-by: Laszlo Agocs --- src/plugins/generic/evdevmouse/qevdevmouse.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/plugins/generic/evdevmouse/qevdevmouse.cpp b/src/plugins/generic/evdevmouse/qevdevmouse.cpp index 0b72123c02..be779c68a5 100644 --- a/src/plugins/generic/evdevmouse/qevdevmouse.cpp +++ b/src/plugins/generic/evdevmouse/qevdevmouse.cpp @@ -176,12 +176,27 @@ void QEvdevMouseHandler::readMouseData() sendMouseEvent(); pendingMouseEvent = false; - } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) { + } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_JOYSTICK) { Qt::MouseButton button = Qt::NoButton; + // BTN_LEFT == 0x110 in kernel's input.h + // The range of possible mouse buttons ends just before BTN_JOYSTICK, value 0x120. switch (data->code) { - case BTN_LEFT: button = Qt::LeftButton; break; - case BTN_MIDDLE: button = Qt::MidButton; break; - case BTN_RIGHT: button = Qt::RightButton; break; + case 0x110: button = Qt::LeftButton; break; // BTN_LEFT + case 0x111: button = Qt::RightButton; break; + case 0x112: button = Qt::MiddleButton; break; + case 0x113: button = Qt::ExtraButton1; break; // AKA Qt::BackButton + case 0x114: button = Qt::ExtraButton2; break; // AKA Qt::ForwardButton + case 0x115: button = Qt::ExtraButton3; break; // AKA Qt::TaskButton + case 0x116: button = Qt::ExtraButton4; break; + case 0x117: button = Qt::ExtraButton5; break; + case 0x118: button = Qt::ExtraButton6; break; + case 0x119: button = Qt::ExtraButton7; break; + case 0x11a: button = Qt::ExtraButton8; break; + case 0x11b: button = Qt::ExtraButton9; break; + case 0x11c: button = Qt::ExtraButton10; break; + case 0x11d: button = Qt::ExtraButton11; break; + case 0x11e: button = Qt::ExtraButton12; break; + case 0x11f: button = Qt::ExtraButton13; break; } if (data->value) m_buttons |= button; -- cgit v1.2.3 From fb8c95bac09910c4dfa476ab97c6206b2e94ee53 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 Feb 2012 15:07:12 +0100 Subject: Automatic metatype registration of two-template-argument types. This commit is complimentary to the commit which introduced a similar partial specialization for single template argument types: 6b4f8a68c8da1af7c5be7dc6075b688c9d6ca55f If T and U are available as metatypes, then QHash is too. Change-Id: I09097b954666418b424c8c23577032beb814343a Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 22 ++++ .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 133 +++++++++++++++++++++ 2 files changed, 155 insertions(+) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index beb7294abd..f969875455 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -565,6 +565,7 @@ template class QSet; template class QSharedPointer; template class QMap; template class QHash; +template struct QPair; typedef QList QVariantList; typedef QMap QVariantMap; typedef QHash QVariantHash; @@ -586,6 +587,23 @@ struct QMetaTypeId< SINGLE_ARG_TEMPLATE > \ } \ }; +#define Q_DECLARE_METATYPE_TEMPLATE_2ARG(DOUBLE_ARG_TEMPLATE) \ +template \ +struct QMetaTypeId< DOUBLE_ARG_TEMPLATE > \ +{ \ + enum { \ + Defined = QMetaTypeId2::Defined && QMetaTypeId2::Defined \ + }; \ + static int qt_metatype_id() \ + { \ + static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ + if (!metatype_id.load()) \ + metatype_id.storeRelease(qRegisterMetaType< DOUBLE_ARG_TEMPLATE >( QByteArray(QByteArray(#DOUBLE_ARG_TEMPLATE "<") + QMetaType::typeName(qMetaTypeId()) + ", " + QMetaType::typeName(qMetaTypeId()) + ">").constData(), \ + reinterpret_cast< DOUBLE_ARG_TEMPLATE *>(quintptr(-1)))); \ + return metatype_id.loadAcquire(); \ + } \ +}; + Q_DECLARE_METATYPE_TEMPLATE_1ARG(QList) Q_DECLARE_METATYPE_TEMPLATE_1ARG(QVector) Q_DECLARE_METATYPE_TEMPLATE_1ARG(QQueue) @@ -594,6 +612,10 @@ Q_DECLARE_METATYPE_TEMPLATE_1ARG(QSet) Q_DECLARE_METATYPE_TEMPLATE_1ARG(QSharedPointer) Q_DECLARE_METATYPE_TEMPLATE_1ARG(QLinkedList) +Q_DECLARE_METATYPE_TEMPLATE_2ARG(QHash) +Q_DECLARE_METATYPE_TEMPLATE_2ARG(QMap) +Q_DECLARE_METATYPE_TEMPLATE_2ARG(QPair) + inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info, Creator creator, Deleter deleter, diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 06919c6f58..f8403f11a1 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -1053,6 +1053,61 @@ void tst_QMetaType::registerStreamBuiltin() Q_DECLARE_METATYPE(QSharedPointer) +typedef QHash IntUIntHash; +Q_DECLARE_METATYPE(IntUIntHash) +typedef QMap IntUIntMap; +Q_DECLARE_METATYPE(IntUIntMap) +typedef QPair IntUIntPair; +Q_DECLARE_METATYPE(IntUIntPair) + +struct CustomComparable +{ + CustomComparable(int i_ = 0) :i(i_) { } + bool operator==(const CustomComparable &other) const + { + return i == other.i; + } + int i; +}; + +struct UnregisteredType {}; + +typedef QHash IntComparableHash; +Q_DECLARE_METATYPE(IntComparableHash) +typedef QMap IntComparableMap; +Q_DECLARE_METATYPE(IntComparableMap) +typedef QPair IntComparablePair; +Q_DECLARE_METATYPE(IntComparablePair) + +typedef QHash IntIntHash; +typedef int NaturalNumber; +class AutoMetaTypeObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(IntIntHash someHash READ someHash CONSTANT) + Q_PROPERTY(NaturalNumber someInt READ someInt CONSTANT) +public: + AutoMetaTypeObject(QObject *parent = 0) + : QObject(parent), m_int(42) + { + m_hash.insert(4, 2); + } + + QHash someHash() const + { + return m_hash; + } + + int someInt() const + { + return m_int; + } + +private: + QHash m_hash; + int m_int; +}; + void tst_QMetaType::automaticTemplateRegistration() { { @@ -1094,6 +1149,84 @@ void tst_QMetaType::automaticTemplateRegistration() vectorList << sharedPointerList; QVERIFY(QVariant::fromValue(vectorList).value > > >().first().first() == testObject); } + { + IntIntHash intIntHash; + intIntHash.insert(4, 2); + QCOMPARE(QVariant::fromValue(intIntHash).value().value(4), 2); + + AutoMetaTypeObject amto; + + qRegisterMetaType >("IntIntHash"); + QVariant hashVariant = amto.property("someHash"); + QCOMPARE(hashVariant.value().value(4), 2); + + qRegisterMetaType("NaturalNumber"); + QVariant intVariant = amto.property("someInt"); + QCOMPARE(intVariant.value(), 42); + } + { + IntUIntHash intUIntHash; + intUIntHash.insert(4, 2); + QCOMPARE(QVariant::fromValue(intUIntHash).value().value(4), (uint)2); + } + { + IntComparableHash intComparableHash; + CustomComparable m; + intComparableHash.insert(4, m); + QCOMPARE(QVariant::fromValue(intComparableHash).value().value(4), m); + } + { + QVariantHash variantHash; + variantHash.insert(QStringLiteral("4"), 2); + QCOMPARE(QVariant::fromValue(variantHash).value().value(QStringLiteral("4")), QVariant(2)); + } + { + typedef QMap IntIntMap; + IntIntMap intIntMap; + intIntMap.insert(4, 2); + QCOMPARE(QVariant::fromValue(intIntMap).value().value(4), 2); + } + { + IntUIntMap intUIntMap; + intUIntMap.insert(4, 2); + QCOMPARE(QVariant::fromValue(intUIntMap).value().value(4), (uint)2); + } + { + IntComparableMap intComparableMap; + CustomComparable m; + intComparableMap.insert(4, m); + QCOMPARE(QVariant::fromValue(intComparableMap).value().value(4), m); + } + { + QVariantMap variantMap; + variantMap.insert(QStringLiteral("4"), 2); + QCOMPARE(QVariant::fromValue(variantMap).value().value(QStringLiteral("4")), QVariant(2)); + } + { + typedef QPair IntIntPair; + IntIntPair intIntPair = qMakePair(4, 2); + QCOMPARE(QVariant::fromValue(intIntPair).value().first, 4); + QCOMPARE(QVariant::fromValue(intIntPair).value().second, 2); + } + { + IntUIntPair intUIntPair = qMakePair(4, 2); + QCOMPARE(QVariant::fromValue(intUIntPair).value().first, 4); + QCOMPARE(QVariant::fromValue(intUIntPair).value().second, (uint)2); + } + { + CustomComparable m; + IntComparablePair intComparablePair = qMakePair(4, m); + QCOMPARE(QVariant::fromValue(intComparablePair).value().first, 4); + QCOMPARE(QVariant::fromValue(intComparablePair).value().second, m); + } + { + typedef QHash IntUnregisteredTypeHash; + QVERIFY(qRegisterMetaType("IntUnregisteredTypeHash") > 0); + } + { + typedef QList UnregisteredTypeList; + QVERIFY(qRegisterMetaType("UnregisteredTypeList") > 0); + } } // Compile-time test, it should be possible to register function pointer types -- cgit v1.2.3 From 099029a3425bf44704672b8105b91968a3a46148 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 1 Mar 2012 17:31:37 +0100 Subject: Fix QPixmap::grabWidget() on Windows. Do not draw on the backingstore DC when drawing to a pixmap. Access the paintdevice for checking via the QPaintEngine since QPainter returns the clipdevice, which is a widget. Fix warning about accessing handle of 0-window in the test. Task-number: QTBUG-24183 Change-Id: Ie91ea6ab9d09528c7ec1d35633f9a0ee667719b1 Reviewed-by: Miikka Heikkinen Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsxpstyle.cpp | 7 +++++-- tests/auto/gui/image/qpixmap/qpixmap.pro | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index a24f42c5f1..5aab69983c 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -339,7 +339,7 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) // Find top level with native window (there might be dialogs that do not have one). foreach (const QWidget *toplevel, QApplication::topLevelWidgets()) - if (toplevel->windowHandle()) + if (toplevel->windowHandle() && toplevel->windowHandle()->handle()) if (const HWND topLevelHwnd = QApplicationPrivate::getHWNDForWidget(toplevel)) return topLevelHwnd; @@ -698,7 +698,10 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) } // Draw on backing store DC only for real widgets. - const bool useFallback = !themeData.widget || painter->device()->devType() != QInternal::Widget + // Access paintDevice via engine since the painter may + // return the clip device which can still be a widget device in case of grabWidget(). + const bool useFallback = !themeData.widget + || painter->paintEngine()->paintDevice()->devType() != QInternal::Widget || painter->opacity() != 1.0 || themeData.rotate || complexXForm || themeData.mirrorVertically || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0) diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro index 91d93a781d..15098770c6 100644 --- a/tests/auto/gui/image/qpixmap/qpixmap.pro +++ b/tests/auto/gui/image/qpixmap/qpixmap.pro @@ -10,5 +10,3 @@ SOURCES += tst_qpixmap.cpp RESOURCES += qpixmap.qrc TESTDATA += convertFromImage/* convertFromToHICON/* loadFromData/* images/* - -win32:CONFIG += insignificant_test # QTBUG-24183 -- cgit v1.2.3 From eab53a13f51bbb07b4e1549cbaf44a2f8a8d8985 Mon Sep 17 00:00:00 2001 From: Andreas Holzammer Date: Fri, 2 Mar 2012 11:02:03 +0100 Subject: Link against the precompiled header. This fixes the build for Visual Studio 2011. Change-Id: I8c43eef851d76f8cdde13a57ea3dcd9cf32df0ab Reviewed-by: Friedemann Kleint --- tools/configure/Makefile.win32 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/configure/Makefile.win32 b/tools/configure/Makefile.win32 index 92de55f137..d2193d7619 100644 --- a/tools/configure/Makefile.win32 +++ b/tools/configure/Makefile.win32 @@ -65,7 +65,8 @@ OBJECTS = \ qxmlutils.obj \ quuid.obj \ qcryptographichash.obj \ - registry.obj + registry.obj \ + configure_pch.obj $(TARGET): $(OBJECTS) $(LINK) $(LFLAGS) /OUT:$(TARGET) @<< -- cgit v1.2.3 From 53229ec8f79c4895e0476d1f3fb950f0427ba427 Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 1 Mar 2012 16:41:39 +0100 Subject: Add note about failing test when using shared-mime-info < 1.0 Change-Id: I3ba9d14d915a579b9e102114866f6c9e0344ba16 Reviewed-by: Friedemann Kleint --- tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 200944d198..63adcadb86 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -721,6 +721,9 @@ void tst_QMimeDatabase::findByFile_data() findByFileName_data(); } +// Note: this test fails on "testcompress.z" when using a shared-mime-info older than 1.0. +// This because of commit 0f9a506069c in shared-mime-info, which fixed the writing of +// case-insensitive patterns into mime.cache. void tst_QMimeDatabase::findByFile() { QFETCH(QString, filePath); -- cgit v1.2.3 From 62a654cc902197cc99326879076ba53b6509dc67 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 1 Mar 2012 13:19:24 +0200 Subject: Fix QApplication autotest crash when running on multiple screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screens need to be destroyed in reverse order to ensure the primary screen stays valid when other screens are destroyed. Task-number: QTBUG-24300 Change-Id: I9d9d710aa67ec045baa8bf292833ffe7d9eea935 Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 6 ++++++ src/plugins/platforms/windows/qwindowsscreen.h | 6 +++++- src/plugins/platforms/xcb/qxcbconnection.cpp | 4 +++- tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp | 3 --- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index be061547a9..5493b21c34 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -97,6 +97,7 @@ private: QScopedPointer mAccessibility; QScopedPointer mPlatformTheme; + QList mScreens; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index fb8e487029..626a7fe0f9 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -134,6 +134,7 @@ QCocoaIntegration::QCocoaIntegration() NSArray *screens = [NSScreen screens]; for (uint i = 0; i < [screens count]; i++) { QCocoaScreen *screen = new QCocoaScreen(i); + mScreens.append(screen); screenAdded(screen); } @@ -142,6 +143,11 @@ QCocoaIntegration::QCocoaIntegration() QCocoaIntegration::~QCocoaIntegration() { [[NSApplication sharedApplication] setDelegate: 0]; + + // Delete screens in reverse order to avoid crash in case of multiple screens + while (!mScreens.isEmpty()) { + delete mScreens.takeLast(); + } } bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 436cc2c0d9..77a327a62a 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -115,7 +115,11 @@ public: QWindowsScreenManager(); - inline void clearScreens() { qDeleteAll(m_screens); m_screens.clear(); } + inline void clearScreens() { + // Delete screens in reverse order to avoid crash in case of multiple screens + while (!m_screens.isEmpty()) + delete m_screens.takeLast(); + } void handleScreenChanges(); bool handleDisplayChange(WPARAM wParam, LPARAM lParam); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 04c43eb97f..9a68d85a63 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -191,7 +191,9 @@ QXcbConnection::~QXcbConnection() { delete m_clipboard; - qDeleteAll(m_screens); + // Delete screens in reverse order to avoid crash in case of multiple screens + while (!m_screens.isEmpty()) + delete m_screens.takeLast(); #ifdef XCB_USE_XINPUT2_MAEMO finalizeXInput2(); diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 98872cb2f6..9bbb6aa7f6 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -605,9 +605,6 @@ public slots: void tst_QApplication::quitOnLastWindowClosed() { -#ifdef Q_OS_WIN32 - QSKIP("This test crashes on Windows. Remove skip once the issue causing the crash is fixed (QTBUG-24300)."); -#endif #ifndef Q_OS_MAC // Test hangs on Mac OS X, see QTBUG-24319 { -- cgit v1.2.3 From 17ddce4692b31af4374b28cd40b9f25e8ed629cd Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 24 Feb 2012 11:11:02 +0100 Subject: Remove Q_BYTE_ORDER and -*-endian arguments from configures Do not write Q_BYTE_ORDER to qconfig.h in the configures. Instead, we #define Q_BYTE_ORDER in qprocessordetection.h, since many CPUs only support a single endian format. For bi-endian processors, we set Q_BYTE_ORDER depending on how the preprocessor sets __BYTE_ORDER__, __BIG_ENDIAN__, or __LITTLE_ENDIAN__ (instead of using a compile test to do so). For operating systems that only support a single byte order, we can check for Q_OS_* in addition to the preprocessor macros above. This is possible because qprocessordetection.h is included by qglobal.h after Q_OS_* and Q_CC_* detection has been done. Do this for Windows CE, which is always little- endian according to MSDN. Change-Id: I019a95e05252ef69895c4b38fbfa6ebfb6a943cd Reviewed-by: Oswald Buddenhagen --- config.tests/unix/endian.test | 60 ---------------- config.tests/unix/endian/endiantest.cpp | 56 --------------- config.tests/unix/endian/endiantest.pro | 3 - configure | 114 ------------------------------- configure.bat | 4 +- src/corelib/global/qprocessordetection.h | 76 ++++++++++++++++++++- tools/configure/configureapp.cpp | 4 -- 7 files changed, 76 insertions(+), 241 deletions(-) delete mode 100755 config.tests/unix/endian.test delete mode 100644 config.tests/unix/endian/endiantest.cpp delete mode 100644 config.tests/unix/endian/endiantest.pro diff --git a/config.tests/unix/endian.test b/config.tests/unix/endian.test deleted file mode 100755 index a662011a27..0000000000 --- a/config.tests/unix/endian.test +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -QMKSPEC=$1 -VERBOSE=$2 -SRCDIR=$3 -OUTDIR=$4 -QMFLAGS=$5 - -# debuggery -[ "$VERBOSE" = "yes" ] && echo "Determining machine byte-order... ($*)" - -# build and run a test program -test -d "$OUTDIR/config.tests/unix/endian" || mkdir -p "$OUTDIR/config.tests/unix/endian" -"$OUTDIR/bin/qmake" -nocache -spec "$QMKSPEC" "QT_BUILD_TREE=$OUTDIR" $QMFLAGS "$SRCDIR/config.tests/unix/endian/endiantest.pro" -o "$OUTDIR/config.tests/unix/endian/Makefile" >/dev/null 2>&1 -cd "$OUTDIR/config.tests/unix/endian" - - -ENDIAN="UNKNOWN" -[ "$VERBOSE" = "yes" ] && $MAKE || $MAKE >/dev/null 2>&1 - -if [ -f ./endiantest.exe ]; then - binary=./endiantest.exe -else - binary=./endiantest -fi - - -if [ -f $binary ]; then - : # nop -else - [ "$VERBOSE" = "yes" ] && echo "Unknown byte order!" - exit 2 -fi - -if strings - $binary | grep LeastSignificantByteFirst >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Found 'LeastSignificantByteFirst' in binary" - ENDIAN="LITTLE" -elif strings - $binary | grep MostSignificantByteFirst >/dev/null 2>&1; then - [ "$VERBOSE" = "yes" ] && echo " Found 'MostSignificantByteFirst' in binary" - ENDIAN="BIG" -fi - -# make clean as this tests is compiled for both the host and the target -if [ "$VERBOSE" = "yes" ]; then - $MAKE distclean -else - $MAKE distclean >/dev/null 2>&1 -fi - -# done -if [ "$ENDIAN" = "LITTLE" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using little endian." - exit 0 -elif [ "$ENDIAN" = "BIG" ]; then - [ "$VERBOSE" = "yes" ] && echo "Using big endian." - exit 1 -else - [ "$VERBOSE" = "yes" ] && echo "Unknown byte order!" - exit 2 -fi diff --git a/config.tests/unix/endian/endiantest.cpp b/config.tests/unix/endian/endiantest.cpp deleted file mode 100644 index e08a11b944..0000000000 --- a/config.tests/unix/endian/endiantest.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the config.tests of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// "MostSignificantByteFirst" -short msb_bigendian[] = { 0x0000, 0x4d6f, 0x7374, 0x5369, 0x676e, 0x6966, 0x6963, 0x616e, 0x7442, 0x7974, 0x6546, 0x6972, 0x7374, 0x0000 }; - -// "LeastSignificantByteFirst" -short lsb_littleendian[] = { 0x0000, 0x654c, 0x7361, 0x5374, 0x6769, 0x696e, 0x6966, 0x6163, 0x746e, 0x7942, 0x6574, 0x6946, 0x7372, 0x0074, 0x0000 }; - -int main(int, char **) -{ - // make sure the linker doesn't throw away the arrays - void (*msb_bigendian_string)() = (void (*)())msb_bigendian; - void (*lsb_littleendian_string)() = (void (*)())lsb_littleendian; - (void)msb_bigendian_string(); - (void)lsb_littleendian_string(); - return msb_bigendian[1] == lsb_littleendian[1]; -} diff --git a/config.tests/unix/endian/endiantest.pro b/config.tests/unix/endian/endiantest.pro deleted file mode 100644 index 7b739eb3f2..0000000000 --- a/config.tests/unix/endian/endiantest.pro +++ /dev/null @@ -1,3 +0,0 @@ -SOURCES = endiantest.cpp -CONFIG -= qt dylib -mac:CONFIG -= app_bundle diff --git a/configure b/configure index cde6dccfa1..674462e928 100755 --- a/configure +++ b/configure @@ -763,8 +763,6 @@ CFG_AVX=auto CFG_REDUCE_RELOCATIONS=auto CFG_NAS=no CFG_ACCESSIBILITY=auto -CFG_ENDIAN=auto -CFG_HOST_ENDIAN=auto CFG_IWMMXT=no CFG_NEON=auto CFG_CLOCK_GETTIME=auto @@ -1035,14 +1033,6 @@ while [ "$#" -gt 0 ]; do VAL=$1 fi ;; - -host-*-endian) - VAR=host_endian - VAL=`echo $1 | sed "s,^-.*-\(.*\)-.*,\1,"` - ;; - -*-endian) - VAR=endian - VAL=`echo $1 | sed "s,^-\(.*\)-.*,\1,"` - ;; -qtnamespace) VAR="qtnamespace" shift @@ -1228,24 +1218,6 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; - endian) - if [ "$VAL" = "little" ]; then - CFG_ENDIAN="Q_LITTLE_ENDIAN" - elif [ "$VAL" = "big" ]; then - CFG_ENDIAN="Q_BIG_ENDIAN" - else - UNKNOWN_OPT=yes - fi - ;; - host_endian) - if [ "$VAL" = "little" ]; then - CFG_HOST_ENDIAN="Q_LITTLE_ENDIAN" - elif [ "$VAL" = "big" ]; then - CFG_HOST_ENDIAN="Q_BIG_ENDIAN" - else - UNKNOWN_OPT=yes - fi - ;; opengl) if [ "$VAL" = "auto" ] || [ "$VAL" = "desktop" ] || [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || @@ -3727,16 +3699,6 @@ if [ "$PLATFORM_QPA" = "yes" ]; then -feature- .. Compile in . The available features are described in src/corelib/global/qfeatures.txt - -little-endian ...... Target platform is little endian (LSB first). - -big-endian ......... Target platform is big endian (MSB first). - - -host-little-endian . Host platform is little endian (LSB first). - -host-big-endian .... Host platform is big endian (MSB first). - - You only need to specify the endianness when - cross-compiling, otherwise the host - endianness will be used. - -no-freetype ........ Do not compile in Freetype2 support. -qt-freetype ........ Use the libfreetype bundled with Qt. * -system-freetype .... Use libfreetype from the operating system. @@ -5532,48 +5494,6 @@ if [ "$CFG_LIBFREETYPE" = "auto" ]; then fi fi -if [ "$CFG_ENDIAN" = "auto" ]; then - if [ "$XPLATFORM_MINGW" = "yes" ]; then - CFG_ENDIAN="Q_LITTLE_ENDIAN" - else - "$unixtests/endian.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" "QMAKE_LFLAGS+=$SYSROOT_FLAG" - F="$?" - if [ "$F" -eq 0 ]; then - CFG_ENDIAN="Q_LITTLE_ENDIAN" - elif [ "$F" -eq 1 ]; then - CFG_ENDIAN="Q_BIG_ENDIAN" - else - echo - echo "The target system byte order could not be detected!" - echo "Turn on verbose messaging (-v) to see the final report." - echo "You can use the -little-endian or -big-endian switch to" - echo "$0 to continue." - exit 101 - fi - fi -fi - -if [ "$CFG_HOST_ENDIAN" = "auto" ]; then - if [ "$BUILD_ON_MAC" = "yes" ]; then - true #leave as auto - else - "$unixtests/endian.test" "$QMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" - F="$?" - if [ "$F" -eq 0 ]; then - CFG_HOST_ENDIAN="Q_LITTLE_ENDIAN" - elif [ "$F" -eq 1 ]; then - CFG_HOST_ENDIAN="Q_BIG_ENDIAN" - else - echo - echo "The host system byte order could not be detected!" - echo "Turn on verbose messaging (-v) to see the final report." - echo "You can use the -host-little-endian or -host-big-endian switch to" - echo "$0 to continue." - exit 101 - fi - fi -fi - HAVE_STL=no if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS; then HAVE_STL=yes @@ -6447,41 +6367,7 @@ cat >>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" -if [ "$CFG_HOST_ENDIAN" = "auto" ]; then - cat >>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" -fi -echo "#else" >>"$outpath/src/corelib/global/qconfig.h.new" -if [ "$CFG_ENDIAN" = "auto" ]; then - cat >>"$outpath/src/corelib/global/qconfig.h.new" <>"$outpath/src/corelib/global/qconfig.h.new" -fi -echo "#endif" >>"$outpath/src/corelib/global/qconfig.h.new" CFG_ARCH_STR=`echo $CFG_ARCH | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` CFG_HOST_ARCH_STR=`echo $CFG_HOST_ARCH | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` diff --git a/configure.bat b/configure.bat index f0b6ce5310..b5ffb14731 100644 --- a/configure.bat +++ b/configure.bat @@ -67,9 +67,7 @@ if not exist src\corelib\global\qconfig.h ( md src\corelib\global if errorlevel 1 goto exit ) - echo #define Q_BIG_ENDIAN 4321 > src\corelib\global\qconfig.h - echo #define Q_LITTLE_ENDIAN 1234 >> src\corelib\global\qconfig.h - echo #define Q_BYTE_ORDER Q_LITTLE_ENDIAN >> src\corelib\global\qconfig.h + echo /* Generated by configure.bat - DO NOT EDIT! */ > src\corelib\global\qconfig.h ) if not exist tools\configure ( diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index fd02f0e4c5..4213d5830e 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -53,16 +53,39 @@ The first is always defined. Defines for the various revisions/variants are optional and usually dependent on how the compiler was invoked. Variants that are a superset of another should have a define for the superset. + + In addition to the procesor family, variants, and revisions, we also set + Q_BYTE_ORDER appropriately for the target processor. For bi-endian + processors, we try to auto-detect the byte order using the __BIG_ENDIAN__, + __LITTLE_ENDIAN__, or __BYTE_ORDER__ preprocessor macros. */ +/* Machine byte-order, reuse preprocessor provided macros when available */ +#if defined(__ORDER_BIG_ENDIAN__) +# define Q_BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#else +# define Q_BIG_ENDIAN 4321 +#endif +#if defined(__ORDER_LITTLE_ENDIAN__) +# define Q_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#else +# define Q_LITTLE_ENDIAN 1234 +#endif + /* Alpha family, no revisions or variants + + Alpha is bi-endian, use endianness auto-detection described above. */ // #elif defined(__alpha__) || defined(_M_ALPHA) // # define Q_PROCESSOR_ALPHA +// Q_BYTE_ORDER not defined, use endianness auto-detection /* - ARM family, known revisions: V5, V6, and V7 + ARM family, known revisions: V5, V6, and V7 + + ARM is bi-endian, detect using __ARMEL__ or __ARMEB__, falling back to + auto-detection described above. */ #if defined(__arm__) || defined(__TARGET_ARCH_ARM) # define Q_PROCESSOR_ARM @@ -88,37 +111,59 @@ || (__TARGET_ARCH_ARM-0 >= 5) # define Q_PROCESSOR_ARM_V5 # endif +# if defined(__ARMEL__) +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# elif defined(__ARMEB__) +# define Q_BYTE_ORDER Q_BIG_ENDIAN +# else +// Q_BYTE_ORDER not defined, use endianness auto-detection +#endif /* AVR32 family, no revisions or variants + + AVR32 is big-endian. */ // #elif defined(__avr32__) // # define Q_PROCESSOR_AVR32 +// # define Q_BYTE_ORDER Q_BIG_ENDIAN /* Blackfin family, no revisions or variants + + Blackfin is little-endian. */ // #elif defined(__bfin__) // # define Q_PROCESSOR_BLACKFIN +// # define Q_BYTE_ORDER Q_LITTLE_ENDIAN /* X86 family, known variants: 32- and 64-bit + + X86 is little-endian. */ #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) # define Q_PROCESSOR_X86 # define Q_PROCESSOR_X86_32 +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) # define Q_PROCESSOR_X86 # define Q_PROCESSOR_X86_64 +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN /* Itanium (IA-64) family, no revisions or variants + + Itanium is bi-endian, use endianness auto-detection described above. */ #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) # define Q_PROCESSOR_IA64 +// Q_BYTE_ORDER not defined, use endianness auto-detection /* MIPS family, known revisions: I, II, III, IV, 32, 64 + + MIPS is bi-endian, use endianness auto-detection described above. */ #elif defined(__mips) || defined(__mips__) || defined(_M_MRX000) # define Q_PROCESSOR_MIPS @@ -143,6 +188,7 @@ # if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) # define Q_PROCESSOR_MIPS_64 # endif +// Q_BYTE_ORDER not defined, use endianness auto-detection /* Power family, known variants: 32- and 64-bit @@ -150,6 +196,8 @@ There are many more known variants/revisions that we do not handle/detect. See http://en.wikipedia.org/wiki/Power_Architecture and http://en.wikipedia.org/wiki/File:PowerISA-evolution.svg + + Power is bi-endian, use endianness auto-detection described above. */ #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \ || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \ @@ -160,34 +208,60 @@ # else # define Q_PROCESSOR_POWER_32 # endif +// Q_BYTE_ORDER not defined, use endianness auto-detection /* S390 family, known variant: S390X (64-bit) + + S390 is big-endian. */ // #elif defined(__s390__) // # define Q_PROCESSOR_S390 // # if defined(__s390x__) // # define Q_PROCESSOR_S390_X // # endif +// # define Q_BYTE_ORDER Q_BIG_ENDIAN /* SuperH family, optional revision: SH-4A + + SuperH is bi-endian, use endianness auto-detection descrived above. */ // #elif defined(__sh__) // # define Q_PROCESSOR_SH // # if defined(__sh4a__) // # define Q_PROCESSOR_SH_4A // # endif +// Q_BYTE_ORDER not defined, use endianness auto-detection /* SPARC family, optional revision: V9 + + SPARC is big-endian only prior to V9, while V9 is bi-endian with big-endian + as the default byte order. Assume all SPARC systems are big-endian. */ // #elif defined(__sparc__) // # define Q_PROCESSOR_SPARC // # if defined(__sparc_v9__) // # define Q_PROCESSOR_SPARC_V9 // # endif +// # define Q_BYTE_ORDER Q_BIG_ENDIAN + +#endif +// Some processors support either endian format, try to detect which we are using. +#if !defined(Q_BYTE_ORDER) +# if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN) +// Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults +# define Q_BYTE_ORDER __BYTE_ORDER__ +# elif defined(__BIG_ENDIAN__) +# define Q_BYTE_ORDER Q_BIG_ENDIAN +# elif defined(__LITTLE_ENDIAN__) \ + || defined(Q_OS_WINCE) // Windows CE is always little-endian according to MSDN. +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN +# else +# error "Unable to determine byte order!" +# endif #endif #endif // QPROCESSORDETECTION_H diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 196fdc9540..b630d289a5 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -2704,10 +2704,6 @@ void Configure::generateConfigfiles() tmpStream << "#define QT_BUILD_INTERNAL" << endl; tmpStream << endl; } - tmpStream << "/* Machine byte-order */" << endl; - tmpStream << "#define Q_BIG_ENDIAN 4321" << endl; - tmpStream << "#define Q_LITTLE_ENDIAN 1234" << endl; - tmpStream << "#define Q_BYTE_ORDER Q_LITTLE_ENDIAN" << endl; if (dictionary[ "QPA" ] == "yes") tmpStream << endl << "#define Q_WS_QPA" << endl; -- cgit v1.2.3 From 70578e4fc7ecb8db30c7ca8b2d427ce99bd35eb4 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 1 Mar 2012 15:35:43 +0100 Subject: Export QPaintEnginePrivate from QtGui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the QCoreGraphicsPaintEngine to use QPaintEnginePrivate members (e.g. pdev and drawBoxTextItem()). Change-Id: I5bed3cb007ae469816afce619edd55f155b04fa9 Reviewed-by: Samuel Rødal --- src/gui/painting/qpaintengine_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h index 594259367c..15495cace8 100644 --- a/src/gui/painting/qpaintengine_p.h +++ b/src/gui/painting/qpaintengine_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QPaintDevice; -class QPaintEnginePrivate +class Q_GUI_EXPORT QPaintEnginePrivate { Q_DECLARE_PUBLIC(QPaintEngine) public: -- cgit v1.2.3 From 286229ca1495c6c872b8e5e0c4bf3dd61c64efda Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Fri, 24 Feb 2012 00:42:34 +1100 Subject: Revert "Don't rely on mapFromGlobal in QGraphicsScenePrivate::itemsAtPosition." This reverts commit 7c0d15a22266a425c9e9ac0120d6774e120fe01e. The commit caused a regression whereby tooltips may be shown even if the mouse is not over the item if it has the Qt::ItemIgnoresTransformations flag and the QGraphicsView had been scaled. Task-number: QTBUG-17517 Task-number: QTBUG-22663 Change-Id: Ib7fd788d9712c5e659fe07182f9505a4eb135ab2 Reviewed-by: Andy Shaw Reviewed-by: Robin Burchell (cherry picked from commit 15c14584199dc43e4a309fc331f3144009008128) --- src/widgets/graphicsview/qgraphicsscene.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 280aa7af8e..51d86dadb1 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -1082,7 +1082,7 @@ void QGraphicsScenePrivate::enableMouseTrackingOnViews() /*! Returns all items for the screen position in \a event. */ -QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*screenPos*/, +QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &screenPos, const QPointF &scenePos, QWidget *widget) const { @@ -1091,12 +1091,16 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*sc if (!view) return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform()); - const QRectF pointRect(scenePos, QSizeF(1, 1)); + const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); if (!view->isTransformed()) return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder); const QTransform viewTransform = view->viewportTransform(); - return q->items(pointRect, Qt::IntersectsItemShape, + if (viewTransform.type() <= QTransform::TxScale) { + return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, + Qt::DescendingOrder, viewTransform); + } + return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, Qt::DescendingOrder, viewTransform); } -- cgit v1.2.3 From 81dcb377e5c53e3e0ec91dffa749da73472b6030 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Wed, 29 Feb 2012 08:18:43 +1100 Subject: Add additional QGraphicsView tests for regression Add additional tests for graphics view tooltip regression introduced by 7c0d15a22266a425c9e9ac0120d6774e120fe01e. Task-number: QTBUG-17517 Task-number: QTBUG-22663 Change-Id: I5e0d0e19504730a3e14ac84712a366dbebe688e6 Reviewed-by: Robin Burchell (cherry picked from commit aaa46755dcc15b8baaa0d1b928828eb60e0babbc) --- .../qgraphicsview/tst_qgraphicsview.cpp | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 84dea04c45..fc49403748 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include #include "../../../platformquirks.h" #include "../../../shared/platforminputcontext.h" @@ -136,6 +137,14 @@ protected: QEvent::Type spied; }; +#if defined QT_BUILD_INTERNAL +class FriendlyGraphicsScene : public QGraphicsScene +{ + friend class tst_QGraphicsView; + Q_DECLARE_PRIVATE(QGraphicsScene); +}; +#endif + class tst_QGraphicsView : public QObject { Q_OBJECT @@ -167,6 +176,10 @@ private slots: void ensureVisibleRect(); void fitInView(); void itemsAtPoint(); +#if defined QT_BUILD_INTERNAL + void itemsAtPosition_data(); + void itemsAtPosition(); +#endif void itemsInRect(); void itemsInRect_cosmeticAdjust_data(); void itemsInRect_cosmeticAdjust(); @@ -1354,6 +1367,54 @@ void tst_QGraphicsView::itemsAtPoint() QCOMPARE(items.takeFirst()->zValue(), qreal(-1)); } +#if defined QT_BUILD_INTERNAL +void tst_QGraphicsView::itemsAtPosition_data() +{ + QTest::addColumn("rotation"); + QTest::addColumn("scale"); + QTest::addColumn("viewPos"); + QTest::addColumn("ignoreTransform"); + QTest::addColumn("hit"); + QTest::newRow("scaled + ignore transform, no hit") << 0.0f << 1000.0f << QPoint(0, 0) << true << false; + QTest::newRow("scaled + ignore transform, hit") << 0.0f << 1000.0f << QPoint(100, 100) << true << true; + QTest::newRow("rotated + scaled, no hit") << 45.0f << 2.0f << QPoint(90, 90) << false << false; + QTest::newRow("rotated + scaled, hit") << 45.0f << 2.0f << QPoint(100, 100) << false << true; +} + +void tst_QGraphicsView::itemsAtPosition() +{ + QFETCH(float, rotation); + QFETCH(float, scale); + QFETCH(QPoint, viewPos); + QFETCH(bool, ignoreTransform); + QFETCH(bool, hit); + + FriendlyGraphicsScene scene; + scene.setSceneRect(QRect(-100, -100, 200, 200)); + QGraphicsItem *item = scene.addRect(-5, -5, 10, 10); + + if (ignoreTransform) + item->setFlag(QGraphicsItem::ItemIgnoresTransformations); + + QGraphicsView view; + view.resize(200, 200); + view.scale(scale, scale); + view.rotate(rotation); + view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view.setScene(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + + QPoint screenPos = view.viewport()->mapToGlobal(viewPos); + QPointF scenePos = view.mapToScene(viewPos); + QGraphicsScenePrivate *viewPrivate = scene.d_func(); + QList items; + items = viewPrivate->itemsAtPosition(screenPos, scenePos, view.viewport()); + QCOMPARE(!items.empty(), hit); +} +#endif + void tst_QGraphicsView::itemsInRect() { QGraphicsScene scene; -- cgit v1.2.3 From b2fb578a115f554ec7a00558978e5532a2ac855a Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Thu, 1 Mar 2012 08:09:26 +1100 Subject: Fix sizing in QGraphicsView itemsAtPosition auto test The auto test may fail incorrectly depending on the width of the QGraphicsView frame. To ensure more consistent test results, the frame is disabled. Change-Id: I8d70fb07e45803230954f776947d525e4cf9050f Reviewed-by: Robin Burchell --- tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index fc49403748..af76b1c3c1 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -1397,6 +1397,7 @@ void tst_QGraphicsView::itemsAtPosition() item->setFlag(QGraphicsItem::ItemIgnoresTransformations); QGraphicsView view; + view.setFrameStyle(QFrame::NoFrame); view.resize(200, 200); view.scale(scale, scale); view.rotate(rotation); -- cgit v1.2.3 From 6c2e57e6884c1ef524bb22f0ed6a2be2c97cd46d Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 1 Mar 2012 11:37:51 +0100 Subject: Make the CONFIG and QT_CONFIG contents available downstream. Change-Id: I62dbc5a695e41179de9f6acd11aa7bc592cac6f3 Reviewed-by: Clinton Stimpson Reviewed-by: Alexander Neundorf Reviewed-by: Stephen Kelly --- src/corelib/Qt5CoreConfigExtras.cmake.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index 67598f4f70..5acc13c6f3 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -30,6 +30,9 @@ list(APPEND Qt5Core_COMPILE_DEFINITIONS QT_NAMESPACE=$$QT_NAMESPACE) set(QT_LIBINFIX \"$${QT_LIBINFIX}\") !!ENDIF +set(QT_CONFIG \"$${CONFIG}\") +set(QT_QCONFIG \"$${QT_CONFIG}\") + !!IF !isEmpty(CMAKE_WINDOWS_BUILD) set(Qt5Core_QTMAIN_LIBRARIES Qt5::WinMain) -- cgit v1.2.3 From c0af324071e6c93129589f7014be7d243a482c25 Mon Sep 17 00:00:00 2001 From: Kevin Krammer Date: Tue, 28 Feb 2012 15:48:57 +0100 Subject: Fixing z-ordering of windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The application root window is at z-order == 0, all platform windows created for Qt windows are its descendants, so their base value for z-order needs to be 1. Change-Id: I7c9615ffac6757c31900a7640eb0ffdd6065b722 Reviewed-by: Sean Harmer Reviewed-by: Nick Ratelle Reviewed-by: Jørgen Lind Reviewed-by: Kevin Krammer --- src/plugins/platforms/blackberry/qbbscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/blackberry/qbbscreen.cpp b/src/plugins/platforms/blackberry/qbbscreen.cpp index 39d2136b7d..11e40f6150 100644 --- a/src/plugins/platforms/blackberry/qbbscreen.cpp +++ b/src/plugins/platforms/blackberry/qbbscreen.cpp @@ -286,7 +286,7 @@ void QBBScreen::updateHierarchy() #endif QList::iterator it; - int topZorder = 0; + int topZorder = 1; // root window is z-order 0, all "top" level windows are "above" it for (it = ms_childWindows.begin(); it != ms_childWindows.end(); it++) (*it)->updateZorder(topZorder); -- cgit v1.2.3 From 08cc2d27794e6bafb75cdc35b6966def35f9facb Mon Sep 17 00:00:00 2001 From: Kevin Krammer Date: Tue, 28 Feb 2012 16:35:08 +0100 Subject: Improving clipboard integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Derive a data accessor class from QMimeData so application level code can query MIME type availability through it or directly attempt to fetch data by MIME type even if the type is not yet known to QBBClipboard. Also make sure any MIME type used by the application in setMimeData operations is checked for availability when being queried for formats. Change-Id: If8174adf3f3383496a354d291ef7d36b9732be1d Reviewed-by: Jørgen Lind --- src/plugins/platforms/blackberry/qbbclipboard.cpp | 184 +++++++++++++++++----- src/plugins/platforms/blackberry/qbbclipboard.h | 5 +- 2 files changed, 150 insertions(+), 39 deletions(-) diff --git a/src/plugins/platforms/blackberry/qbbclipboard.cpp b/src/plugins/platforms/blackberry/qbbclipboard.cpp index fce016d5ee..293a0c771b 100644 --- a/src/plugins/platforms/blackberry/qbbclipboard.cpp +++ b/src/plugins/platforms/blackberry/qbbclipboard.cpp @@ -46,6 +46,7 @@ #include #include +#include #include #include @@ -53,11 +54,131 @@ #include QT_BEGIN_NAMESPACE -static const char *typeList[] = {"text/html", "text/plain", "application/x-color"}; + +// null terminated array +static const char *typeList[] = {"text/html", "text/plain", "image/png", "image/jpeg", "application/x-color", 0}; + +static QByteArray readClipboardBuff(const char *type) +{ + char *pbuffer; + if (is_clipboard_format_present(type) == 0) { + int size = get_clipboard_data(type, &pbuffer); + if (size != -1 && pbuffer) { + const QByteArray result = QByteArray(pbuffer, size); + free(pbuffer); + return result; + } + } + + return QByteArray(); +} + +class QBBClipboard::MimeData : public QMimeData +{ + Q_OBJECT +public: + MimeData(QBBClipboard *clipboard) + : QMimeData(), + m_clipboard(clipboard), + m_userMimeData(0) + { + Q_ASSERT(clipboard); + + for (int i = 0; typeList[i] != 0; ++i) { + m_formatsToCheck << QString::fromUtf8(typeList[i]); + } + } + + ~MimeData() + { + delete m_userMimeData; + } + + void addFormatToCheck(const QString &format) { + m_formatsToCheck << format; + +#if defined(QBBCLIPBOARD_DEBUG) + qDebug() << Q_FUNC_INFO << "formats=" << m_formatsToCheck; +#endif + } + + bool hasFormat(const QString &mimetype) const + { + const bool result = is_clipboard_format_present(mimetype.toUtf8().constData()) == 0; +#if defined(QBBCLIPBOARD_DEBUG) + qDebug() << Q_FUNC_INFO << "mimetype=" << mimetype << "result=" << result; +#endif + return result; + } + + QStringList formats() const + { + QStringList result; + + Q_FOREACH (const QString &format, m_formatsToCheck) { + if (is_clipboard_format_present(format.toUtf8().constData()) == 0) + result << format; + } + +#if defined(QBBCLIPBOARD_DEBUG) + qDebug() << Q_FUNC_INFO << "result=" << result; +#endif + return result; + } + + void setUserMimeData(QMimeData *userMimeData) + { + delete m_userMimeData; + m_userMimeData = userMimeData; + + // system clipboard API doesn't allow detection of changes by other applications + // simulate an owner change through delayed invocation + // basically transfer ownership of data to the system clipboard once event processing resumes + if (m_userMimeData) + QMetaObject::invokeMethod(this, "releaseOwnership", Qt::QueuedConnection); + } + + QMimeData *userMimeData() + { + return m_userMimeData; + } + +protected: + QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const + { +#if defined(QBBCLIPBOARD_DEBUG) + qDebug() << Q_FUNC_INFO << "mimetype=" << mimetype << "preferredType=" << preferredType; +#endif + if (is_clipboard_format_present(mimetype.toUtf8().constData()) != 0) + return QMimeData::retrieveData(mimetype, preferredType); + + const QByteArray data = readClipboardBuff(mimetype.toUtf8().constData()); + return qVariantFromValue(data); + } + +private Q_SLOTS: + void releaseOwnership() + { + if (m_userMimeData) { +#if defined(QBBCLIPBOARD_DEBUG) + qDebug() << Q_FUNC_INFO << "user data formats=" << m_userMimeData->formats() << "system formats=" << formats(); +#endif + delete m_userMimeData; + m_userMimeData = 0; + m_clipboard->emitChanged(QClipboard::Clipboard); + } + } + +private: + QBBClipboard * const m_clipboard; + + QSet m_formatsToCheck; + QMimeData *m_userMimeData; +}; QBBClipboard::QBBClipboard() + : m_mimeData(new MimeData(this)) { - m_mimeData = 0; } QBBClipboard::~QBBClipboard() @@ -70,46 +191,37 @@ void QBBClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) if (mode != QClipboard::Clipboard) return; - if (m_mimeData != data) { - delete m_mimeData; - m_mimeData = data; - } + if (data == m_mimeData || data == m_mimeData->userMimeData()) + return; empty_clipboard(); + m_mimeData->clear(); + m_mimeData->setUserMimeData(data); + if (data == 0) return; - QStringList format = data->formats(); - for (int i = 0; i < format.size(); ++i) { - QString type = format.at(i); - QByteArray buf = data->data(type); - if (!buf.size()) - continue; - - int ret = set_clipboard_data(type.toUtf8().data(), buf.size(), buf.data()); + const QStringList formats = data->formats(); #if defined(QBBCLIPBOARD_DEBUG) - qDebug() << "QBB: set " << type.toUtf8().data() << "to clipboard, size=" << buf.size() << ";ret=" << ret; -#else - Q_UNUSED(ret); + qDebug() << Q_FUNC_INFO << "formats=" << formats; #endif - } -} -void QBBClipboard::readClipboardBuff(const char *type) -{ - char *pbuffer; - if (is_clipboard_format_present(type) == 0) { - int size = get_clipboard_data(type, &pbuffer); - if (size != -1 && pbuffer) { - QString qtype = type; + Q_FOREACH (const QString &format, formats) { + const QByteArray buf = data->data(format); + + if (buf.isEmpty()) + continue; + + int ret = set_clipboard_data(format.toUtf8().data(), buf.size(), buf.data()); #if defined(QBBCLIPBOARD_DEBUG) - qDebug() << "QBB: clipboard has " << qtype; + qDebug() << "QBB: set " << format << "to clipboard, size=" << buf.size() << ";ret=" << ret; #endif - m_mimeData->setData(qtype, QByteArray(pbuffer, size)); - delete pbuffer; - } + if (ret) + m_mimeData->addFormatToCheck(format); } + + emitChanged(QClipboard::Clipboard); } QMimeData *QBBClipboard::mimeData(QClipboard::Mode mode) @@ -117,16 +229,16 @@ QMimeData *QBBClipboard::mimeData(QClipboard::Mode mode) if (mode != QClipboard::Clipboard) return 0; - if (!m_mimeData) - m_mimeData = new QMimeData(); + if (m_mimeData->userMimeData()) + return m_mimeData->userMimeData(); m_mimeData->clear(); - for (int i = 0; i < 3; i++) - readClipboardBuff(typeList[i]); - return m_mimeData; } QT_END_NAMESPACE -#endif //QT_NO_CLIPBOAR + +#include "qbbclipboard.moc" + +#endif //QT_NO_CLIPBOARD diff --git a/src/plugins/platforms/blackberry/qbbclipboard.h b/src/plugins/platforms/blackberry/qbbclipboard.h index b9de9b3e36..11a36ba8e5 100644 --- a/src/plugins/platforms/blackberry/qbbclipboard.h +++ b/src/plugins/platforms/blackberry/qbbclipboard.h @@ -44,7 +44,6 @@ #ifndef QT_NO_CLIPBOARD #include -#include QT_BEGIN_NAMESPACE @@ -57,8 +56,8 @@ public: virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); private: - QMimeData *m_mimeData; - void readClipboardBuff(const char *type); + class MimeData; + MimeData *m_mimeData; }; QT_END_NAMESPACE -- cgit v1.2.3 From ab05682564da139a7b0bca6817854abc58486d49 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 2 Mar 2012 11:56:16 +0100 Subject: don't announce a dynamic .qmake.cache if we don't actually create one otherwise we are breaking the "less hacky" configurations. whoops. Change-Id: Ibb037753fbaf30beae3d30173be77d48b978b60b Reviewed-by: Caroline Chao --- mkspecs/features/default_pre.prf | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf index 9e142f172d..59a7e4cb14 100644 --- a/mkspecs/features/default_pre.prf +++ b/mkspecs/features/default_pre.prf @@ -46,9 +46,10 @@ CONFIG = lex yacc warn_on debug uic resources $$CONFIG } else { error("Failed to run: $$MSG") } - unset(QTFWD) - unset(PRO_BASENAME) # Let qmake know about the unexpectedly appearing cache file. - _QMAKE_CACHE_ = $$QMAKE_SYNCQT_OUTDIR/.qmake.cache + contains(QTFWD, -cache-module-fwd):_QMAKE_CACHE_ = $$QMAKE_SYNCQT_OUTDIR/.qmake.cache + + unset(QTFWD) + unset(PRO_BASENAME) } -- cgit v1.2.3 From db5c28fa0e392a68836d9a97bb2add3a94ddb37c Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Fri, 2 Mar 2012 15:05:59 +0100 Subject: Use correct types in QResource. qHash() returns uint, not int, so change all interactions with hashing to use uint to match. This blocks the introduction of a new (better) hashing algorithm because it currently breaks numerous tests: rcc would (correctly) write a uint hash value to the qrc files, but QResource would attempt to mangle it around as an int. This wasn't a problem with the old hash, because it deliberately threw away data (h &= 0x0fffffff), possibly because of someone not being able to diagnose precisly this problem. Change-Id: I46fb42acc100fdd3bedd714f6dc91aeca91d0351 Reviewed-by: hjk --- src/corelib/io/qresource.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index e46ab260b0..fb3a24b940 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -114,7 +114,7 @@ class QResourceRoot }; const uchar *tree, *names, *payloads; inline int findOffset(int node) const { return node * 14; } //sizeof each tree element - int hash(int node) const; + uint hash(int node) const; QString name(int node) const; short flags(int node) const; public: @@ -594,7 +594,7 @@ QResource::searchPaths() return *resourceSearchPaths(); } -inline int QResourceRoot::hash(int node) const +inline uint QResourceRoot::hash(int node) const { if(!node) //root return 0; @@ -673,13 +673,13 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const qDebug() << " " << child+j << " :: " << name(child+j); } #endif - const int h = qHash(segment); + const uint h = qHash(segment); //do the binary search for the hash int l = 0, r = child_count-1; int sub_node = (l+r+1)/2; while(r != l) { - const int sub_node_hash = hash(child+sub_node); + const uint sub_node_hash = hash(child+sub_node); if(h == sub_node_hash) break; else if(h < sub_node_hash) -- cgit v1.2.3 From db1aa6dd99aa7ce3118452c811dcf88a863511d7 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 2 Mar 2012 13:47:47 +0200 Subject: Fix QWizard autotest for Windows 7 Classic theme QWizard always forced Aero style even if Classic theme was used. Added a check for Classic theme into initialization. Task-number: QTBUG-24618 Change-Id: I0793df62e022037835e1c1a311143f06cc4382b4 Reviewed-by: Friedemann Kleint --- src/widgets/dialogs/qwizard.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 324831ea52..8cd3799cae 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -3141,7 +3141,12 @@ bool QWizard::event(QEvent *event) #if !defined(QT_NO_STYLE_WINDOWSVISTA) else if (event->type() == QEvent::Show && d->vistaInitPending) { d->vistaInitPending = false; - d->wizStyle = AeroStyle; + // Do not force AeroStyle when in Classic theme. + // Note that d->handleAeroStyleChange() needs to be called in any case as it does some + // necessary initialization, like ensures that the Aero specific back button is hidden if + // Aero theme isn't active. + if (QVistaHelper::vistaState() != QVistaHelper::Classic) + d->wizStyle = AeroStyle; d->handleAeroStyleChange(); } else if (d->isVistaThemeEnabled()) { -- cgit v1.2.3 From c531fcc92eeae600732d8e9fb63b70889322c018 Mon Sep 17 00:00:00 2001 From: Jan-Arve Saether Date: Fri, 2 Mar 2012 16:06:04 +0100 Subject: Improve debugging in the windows accessibility bridge. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit set QT_DEBUG_ACCESSIBILITY=(1|0) to turn logging on or off Change-Id: Ibd5b77699decf0cf02bc6b6cc656fa237de29124 Reviewed-by: Jan-Arve Sæther Reviewed-by: Frederik Gladhorn --- src/gui/accessible/qaccessible.cpp | 20 ++++-- .../platforms/windows/qwindowsaccessibility.cpp | 72 +++++++++++++--------- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 37e7a1dbb4..f256480dc8 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1198,11 +1198,23 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface) if (iface->object()) { d << "obj=" << iface->object(); } - if (iface->state().invisible) { - d << "invisible"; - } else { + QStringList stateStrings; + QAccessible::State st = iface->state(); + if (st.focusable) + stateStrings << QLatin1String("focusable"); + if (st.focused) + stateStrings << QLatin1String("focused"); + if (st.selected) + stateStrings << QLatin1String("selected"); + if (st.invisible) + stateStrings << QLatin1String("invisible"); + + if (!stateStrings.isEmpty()) + d << stateStrings.join(QLatin1String("|")); + + if (!st.invisible) d << "rect=" << iface->rect(); - } + } else { d << " invalid"; } diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp index 3ef21fa0b7..4c24cdd8d0 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp @@ -88,23 +88,37 @@ QT_BEGIN_NAMESPACE -//#define DEBUG_SHOW_ATCLIENT_COMMANDS -#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS +#ifndef QT_NO_DEBUG QT_BEGIN_INCLUDE_NAMESPACE -#include +# include QT_END_INCLUDE_NAMESPACE +static inline bool debug_accessibility() +{ + static signed int debugging = -1; + if (debugging == -1) + debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt(); + return !!debugging; +} +# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug +#else +# define accessibleDebug() +#endif -void showDebug(const char* funcName, const QAccessibleInterface *iface) +//#define DEBUG_SHOW_ATCLIENT_COMMANDS +#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS) +void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface) { - qDebug() << "Role:" << qAccessibleRoleString(iface->role(0)) - << "Name:" << iface->text(QAccessible::Name, 0) - << "State:" << QString::number(int(iface->state(0)), 16) - << QLatin1String(funcName); + QString str; + QDebug dbg(&str); + dbg << iface << QLatin1String(funcName); + accessibleDebug("%s", qPrintable(str)); } +# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface) #else -# define showDebug(f, iface) +# define accessibleDebugClientCalls(iface) #endif + typedef QSharedPointer QAIPointer; // This stuff is used for widgets/items with no window handle: @@ -595,7 +609,7 @@ IAccessible::accHitTest documents the value returned in pvarID like this: HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -635,7 +649,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -659,7 +673,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py // moz: [important, but no need to implement up/down/left/right] HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -799,7 +813,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -853,7 +867,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -864,7 +878,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChil // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -887,7 +901,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) { Q_UNUSED(varID); - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -904,7 +918,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) { Q_UNUSED(varID); - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -919,7 +933,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -944,7 +958,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -974,7 +988,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) { Q_UNUSED(varID); - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1004,7 +1018,7 @@ static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAcce // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1040,14 +1054,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1075,7 +1089,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1151,7 +1165,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid() || varID.lVal) return E_FAIL; @@ -1172,7 +1186,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); return DISP_E_MEMBERNOTFOUND; } @@ -1181,7 +1195,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN { Q_UNUSED(flagsSelect); Q_UNUSED(varID); - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1210,7 +1224,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN // moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; @@ -1232,7 +1246,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren) { - showDebug(__FUNCTION__, accessible); + accessibleDebugClientCalls(accessible); if (!accessible->isValid()) return E_FAIL; -- cgit v1.2.3 From 72b5afddb9a47084850af9a403c4a1823336b5cf Mon Sep 17 00:00:00 2001 From: Jan-Arve Saether Date: Fri, 2 Mar 2012 16:51:26 +0100 Subject: Fix get_accFocus() to return CHILDID_SELF when it returns itself. This means that the AT client knows it should not have to ask for the focus child anymore. Previously, some clients (NVDA) kept on asking infinitely because of this. Change-Id: Ia2bd2e1088a899f7d1a0c9189024accdacfd693b Reviewed-by: Frederik Gladhorn --- .../platforms/windows/qwindowsaccessibility.cpp | 48 ++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp index 4c24cdd8d0..1a8f593609 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp @@ -121,6 +121,21 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn typedef QSharedPointer QAIPointer; +static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other) +{ + if (one == other) return true; + if (!one || !other) return false; + + if (one->object() && other->object() && (one->object() == other->object())) + return true; + QAIPointer onePar(one->parent()); + QAIPointer otherPar(other->parent()); + + if (compareAccessible(onePar.data(), otherPar.data())) + return onePar->indexOfChild(one) == otherPar->indexOfChild(other); + return false; +} + // This stuff is used for widgets/items with no window handle: typedef QMap > NotifyMap; Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents) @@ -1221,7 +1236,22 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN return res ? S_OK : S_FALSE; } -// moz: [important] +/*! + \internal + Can return: + + +-------------+------------------------------------------------------------------------------+ + | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child | + | | object that has the keyboard focus. | + +-------------+------------------------------------------------------------------------------+ + moz: [important] +*/ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) { accessibleDebugClientCalls(accessible); @@ -1229,16 +1259,20 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) return E_FAIL; if (QAccessibleInterface *acc = accessible->focusChild()) { - QWindowsAccessible* wacc = new QWindowsAccessible(acc); - IDispatch *iface = 0; - wacc->QueryInterface(IID_IDispatch, (void**)&iface); - if (iface) { + if (compareAccessible(acc, accessible)) { + (*pvarID).vt = VT_I4; + (*pvarID).lVal = CHILDID_SELF; + delete acc; + return S_OK; + } else { + QWindowsAccessible* wacc = new QWindowsAccessible(acc); + IDispatch *iface = 0; + wacc->QueryInterface(IID_IDispatch, (void**)&iface); (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; - } else { - delete wacc; } + delete acc; } (*pvarID).vt = VT_EMPTY; return S_FALSE; -- cgit v1.2.3 From cd6e90c70ac13065257422088ffa01537ed9c685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 28 Feb 2012 09:27:25 +0100 Subject: Remove the LIBS from platformsupport The application / library that uses this should know it needs to link to ie. udev, xrendr etc. Change-Id: I9e3ffd4d98b3bd66abb8e621378b010da7feda7a Reviewed-by: Thiago Macieira Reviewed-by: Laszlo Agocs --- src/platformsupport/glxconvenience/glxconvenience.pri | 1 - src/platformsupport/udev/udev.pri | 1 - 2 files changed, 2 deletions(-) diff --git a/src/platformsupport/glxconvenience/glxconvenience.pri b/src/platformsupport/glxconvenience/glxconvenience.pri index 3632f45b54..6915f8db4e 100644 --- a/src/platformsupport/glxconvenience/glxconvenience.pri +++ b/src/platformsupport/glxconvenience/glxconvenience.pri @@ -1,6 +1,5 @@ contains(QT_CONFIG,xlib):contains(QT_CONFIG,xrender) { contains(QT_CONFIG,opengl):!contains(QT_CONFIG,opengles2) { - LIBS += $$QMAKE_LIBS_X11 -lXrender HEADERS += $$PWD/qglxconvenience_p.h SOURCES += $$PWD/qglxconvenience.cpp } diff --git a/src/platformsupport/udev/udev.pri b/src/platformsupport/udev/udev.pri index 48ad9d36af..21c71d5f5b 100644 --- a/src/platformsupport/udev/udev.pri +++ b/src/platformsupport/udev/udev.pri @@ -1,5 +1,4 @@ contains(QT_CONFIG, libudev) { HEADERS += $$PWD/qudevhelper_p.h $$PWD/qudevicehelper_p.h SOURCES += $$PWD/qudevhelper.cpp $$PWD/qudevicehelper.cpp - LIBS += -ludev } -- cgit v1.2.3 From dce3821b8a6dfbb041d7ecec8b97c960b0e08c51 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 21 Feb 2012 12:56:47 +0100 Subject: make evaluation of spec+cache independent of build pass context don't inject the build pass specific variables into the project even before evaluating the .spec file and the .qmake.cache. they are not supposed to base configuration on that - feature files should do that later. the immediate advantage of this is that base_vars is never manipulated upfront any more, which allows for cleaner setup paths. also, we can do more caching of the spec+cache contents. Change-Id: I19d7f8bec1fb7c3b54121e26794340b287055ebf Reviewed-by: Joerg Bornemann --- dist/changes-5.0.0 | 3 ++- qmake/generators/metamakefile.cpp | 4 ++-- qmake/project.cpp | 4 ++++ qmake/project.h | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 5a9ce7e6c7..ef1bd6d406 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -200,7 +200,8 @@ information about a particular change. - qmake * Projects which explicitly set an empty TARGET are considered broken now. - * several functions and built-in variables were modified to return normalized paths. + * The makespec and .qmake.cache do not see build pass specific variables any more. + * Several functions and built-in variables were modified to return normalized paths. - QTextCodecPlugin has been removed since it is no longer used. All text codecs are now built into QtCore. diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 55ab0a5af5..39dd4ab797 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -243,13 +243,13 @@ MakefileGenerator basecfgs = project->values(build + ".CONFIG"); basecfgs += build; basecfgs += "build_pass"; - basevars["CONFIG"] = basecfgs; basevars["BUILD_PASS"] = QStringList(build); QStringList buildname = project->values(build + ".name"); basevars["BUILD_NAME"] = (buildname.isEmpty() ? QStringList(build) : buildname); //create project - QMakeProject *build_proj = new QMakeProject(project->properties(), basevars); + QMakeProject *build_proj = new QMakeProject(project->properties()); + build_proj->setExtraVars(basevars); build_proj->setExtraConfigs(basecfgs); build_proj->read(project->projectFile()); diff --git a/qmake/project.cpp b/qmake/project.cpp index 8aa3ed2ed6..208d5b7d3e 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1292,6 +1292,10 @@ QMakeProject::read(uchar cmd) vars = base_vars; // start with the base + for (QHash::ConstIterator it = extra_vars.constBegin(); + it != extra_vars.constEnd(); ++it) + vars.insert(it.key(), it.value()); + if(cmd & ReadFeatures) { debug_msg(1, "Processing default_pre: %s", vars["CONFIG"].join("::").toLatin1().constData()); doProjectInclude("default_pre", IncludeFlagFeature, vars); diff --git a/qmake/project.h b/qmake/project.h index 43623a3974..4c99825317 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -85,7 +85,7 @@ class QMakeProject QMakeProperty *prop; void reset(); QStringList extra_configs; - QHash vars, base_vars; + QHash vars, base_vars, extra_vars; bool parse(const QString &text, QHash &place, int line_count=1); enum IncludeStatus { @@ -119,6 +119,7 @@ public: QMakeProject(QMakeProperty *p, const QHash &nvars) { init(p, &nvars); } ~QMakeProject(); + void setExtraVars(const QHash &_vars) { extra_vars = _vars; } void setExtraConfigs(const QStringList &_cfgs) { extra_configs = _cfgs; } enum { ReadProFile=0x01, ReadSetup=0x02, ReadFeatures=0x04, ReadAll=0xFF }; -- cgit v1.2.3 From a30074bab8446640d41060637b99394136bea7d7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 20 Feb 2012 22:19:11 +0100 Subject: remove now unused QMakeProject c'tors Change-Id: Ia65d49df50a5610bbd88417ca90ac348a774a1e1 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 7 +++---- qmake/project.h | 7 ++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 208d5b7d3e..7a5c953f02 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -614,10 +614,8 @@ QMakeProject::~QMakeProject() void -QMakeProject::init(QMakeProperty *p, const QHash *vars) +QMakeProject::init(QMakeProperty *p) { - if(vars) - base_vars = *vars; if(!p) { prop = new QMakeProperty; own_prop = true; @@ -631,7 +629,8 @@ QMakeProject::init(QMakeProperty *p, const QHash *vars) QMakeProject::QMakeProject(QMakeProject *p, const QHash *vars) { - init(p->properties(), vars ? vars : &p->variables()); + init(p->properties()); + base_vars = vars ? *vars : p->variables(); for(QHash::iterator it = p->replaceFunctions.begin(); it != p->replaceFunctions.end(); ++it) { it.value()->ref(); replaceFunctions.insert(it.key(), it.value()); diff --git a/qmake/project.h b/qmake/project.h index 4c99825317..6422ed1f32 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -106,17 +106,14 @@ class QMakeProject bool doProjectCheckReqs(const QStringList &deps, QHash &place); bool doVariableReplace(QString &str, QHash &place); QStringList doVariableReplaceExpand(const QString &str, QHash &place, bool *ok=0); - void init(QMakeProperty *, const QHash *); + void init(QMakeProperty *); QStringList &values(const QString &v, QHash &place); void validateModes(); void resolveSpec(QString *spec, const QString &qmakespec); public: - QMakeProject() { init(0, 0); } - QMakeProject(QMakeProperty *p) { init(p, 0); } + QMakeProject(QMakeProperty *p = 0) { init(p); } QMakeProject(QMakeProject *p, const QHash *nvars=0); - QMakeProject(const QHash &nvars) { init(0, &nvars); } - QMakeProject(QMakeProperty *p, const QHash &nvars) { init(p, &nvars); } ~QMakeProject(); void setExtraVars(const QHash &_vars) { extra_vars = _vars; } -- cgit v1.2.3 From c679b2f0a65a630f7490b37529e2186a8cd9c78b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 2 Feb 2012 19:31:57 +0100 Subject: get rid of Option::user_configs merge them into before_user_vars. they are evaluated right after another anyway. Change-Id: I11859284b363fee01233f6e20989444fef711d0d Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/generators/makefile.cpp | 4 ---- qmake/generators/projectgenerator.cpp | 2 -- qmake/option.cpp | 8 ++++++-- qmake/option.h | 2 +- qmake/project.cpp | 8 -------- 5 files changed, 7 insertions(+), 17 deletions(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index 59a615e63a..8544dce2fc 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2235,10 +2235,6 @@ QString MakefileGenerator::buildArgs(const QString &outdir) ret += " -win32"; } - //configs - for(QStringList::Iterator it = Option::user_configs.begin(); - it != Option::user_configs.end(); ++it) - ret += " -config " + (*it); //arguments for(QStringList::Iterator it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it) { diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index a2eb45ef40..9a181a43f5 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -344,8 +344,6 @@ ProjectGenerator::writeMakefile(QTextStream &t) t << "######################################################################" << endl; t << "# Automatically generated by qmake (" << qmake_version() << ") " << QDateTime::currentDateTime().toString() << endl; t << "######################################################################" << endl << endl; - if(!Option::user_configs.isEmpty()) - t << "CONFIG += " << Option::user_configs.join(" ") << endl; int i; for(i = 0; i < Option::before_user_vars.size(); ++i) t << Option::before_user_vars[i] << endl; diff --git a/qmake/option.cpp b/qmake/option.cpp index c73eb149ec..cf72351f1f 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -91,7 +91,6 @@ QString Option::output_dir; Option::QMAKE_RECURSIVE Option::recursive = Option::QMAKE_RECURSIVE_DEFAULT; QStringList Option::before_user_vars; QStringList Option::after_user_vars; -QStringList Option::user_configs; QString Option::user_template; QString Option::user_template_prefix; QStringList Option::shellPath; @@ -219,6 +218,8 @@ bool usage(const char *a0) int Option::parseCommandLine(int argc, char **argv, int skip) { + QStringList user_configs; + bool before = true; for(int x = skip; x < argc; x++) { if(*argv[x] == '-' && strlen(argv[x]) > 1) { /* options */ @@ -303,7 +304,7 @@ Option::parseCommandLine(int argc, char **argv, int skip) } else if(opt == "nr" || opt == "norecursive") { Option::recursive = Option::QMAKE_RECURSIVE_NO; } else if(opt == "config") { - Option::user_configs += argv[++x]; + user_configs += argv[++x]; } else { if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL) { @@ -376,6 +377,9 @@ Option::parseCommandLine(int argc, char **argv, int skip) } } + if (!user_configs.isEmpty()) + Option::before_user_vars += "CONFIG += " + user_configs.join(" "); + return Option::QMAKE_CMDLINE_SUCCESS; } diff --git a/qmake/option.h b/qmake/option.h index d1bfcd169b..2d0d1114a9 100644 --- a/qmake/option.h +++ b/qmake/option.h @@ -173,7 +173,7 @@ struct Option static int warn_level; enum QMAKE_RECURSIVE { QMAKE_RECURSIVE_DEFAULT, QMAKE_RECURSIVE_YES, QMAKE_RECURSIVE_NO }; static QMAKE_RECURSIVE recursive; - static QStringList before_user_vars, after_user_vars, user_configs; + static QStringList before_user_vars, after_user_vars; enum HOST_MODE { HOST_UNKNOWN_MODE, HOST_UNIX_MODE, HOST_WIN_MODE, HOST_MACX_MODE }; static HOST_MODE host_mode; enum TARG_MODE { TARG_UNKNOWN_MODE, TARG_UNIX_MODE, TARG_WIN_MODE, TARG_MACX_MODE, diff --git a/qmake/project.cpp b/qmake/project.cpp index 7a5c953f02..34e443f5c5 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1321,14 +1321,6 @@ QMakeProject::read(uchar cmd) } } - //commandline configs - if ((cmd & ReadSetup) && !Option::user_configs.isEmpty()) { - parser.file = "(configs)"; - parser.from_file = false; - parser.line_no = 1; //really arg count now.. duh - parse("CONFIG += " + Option::user_configs.join(" "), vars); - } - // After user configs, to override them if (!extra_configs.isEmpty()) { parser.file = "(extra configs)"; -- cgit v1.2.3 From 9c757fac3540f12b066dcecc936714bcd119f155 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 2 Mar 2012 16:33:01 +0100 Subject: xcb: Check for SHAPE extension before using it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change makes sure that the X11 server really supports the SHAPE extension before it is used. Before this, libxcb would disconnect from the server as soon as it was told to send a SHAPE request to a server which doesn't support SHAPE. Oh and of course it would do so without any good error message. Change-Id: I5f9481e488925e74e62f229e9f637ef262020c04 Signed-off-by: Uli Schlachter Reviewed-by: Samuel Rødal --- src/plugins/platforms/xcb/qxcbconnection.cpp | 22 ++++++++++++++++++++++ src/plugins/platforms/xcb/qxcbconnection.h | 6 ++++++ src/plugins/platforms/xcb/qxcbdrag.cpp | 10 ++++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 9a68d85a63..90df387f6a 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -109,6 +109,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char , m_has_support_for_dri2(false) #endif , xfixes_first_event(0) + , has_shape_extension(false) + , has_input_shape(false) { m_primaryScreen = 0; @@ -175,6 +177,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char #ifdef XCB_USE_XINPUT2_MAEMO initializeXInput2(); #endif + initializeXShape(); m_wmSupport.reset(new QXcbWMSupport(this)); m_keyboard = new QXcbKeyboard(this); @@ -1050,6 +1053,25 @@ void QXcbConnection::initializeXRender() #endif } +void QXcbConnection::initializeXShape() +{ + const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id); + if (!xshape_reply || !xshape_reply->present) + return; + + has_shape_extension = true; + xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection); + xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection, + cookie, NULL); + if (!shape_query) { + qWarning("QXcbConnection: Failed to initialize SHAPE extension"); + } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) { + // The input shape is the only thing added in SHAPE 1.1 + has_input_shape = true; + } + free(shape_query); +} + #if defined(XCB_USE_EGL) bool QXcbConnection::hasEgl() const { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7beb41bdd7..34943bfdef 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -354,6 +354,8 @@ public: inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; } bool hasXFixes() const { return xfixes_first_event > 0; } + bool hasXShape() const { return has_shape_extension; } + bool hasInputShape() const { return has_input_shape; } private slots: void processXcbEvents(); @@ -363,6 +365,7 @@ private: void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); void initializeXFixes(); void initializeXRender(); + void initializeXShape(); #ifdef XCB_USE_DRI2 void initializeDri2(); #endif @@ -429,6 +432,9 @@ private: QVector m_peekFuncs; uint32_t xfixes_first_event; + + bool has_shape_extension; + bool has_input_shape; }; #define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index a0736d81f1..3aeaaba2d8 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -216,7 +216,7 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int } static -bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, int shapeType) +bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType) { bool interacts = true; xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL); @@ -263,9 +263,11 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md free(reply); if (isAware) { // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we - // need an && here so that in the case one is set and the other is not we still get the correct result. - windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT) && - windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING); + // need to check both here so that in the case one is set and the other is not we still get the correct result. + if (connection()->hasInputShape()) + windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT); + if (windowContainsMouse && connection()->hasXShape()) + windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING); if (windowContainsMouse) return w; } -- cgit v1.2.3 From 0f4913702702420cc4f849fd83296bee777fab26 Mon Sep 17 00:00:00 2001 From: mae Date: Thu, 1 Mar 2012 19:42:50 +0100 Subject: Name threads properly When there is no QObject subclass with Q_OBJECT macro, we must at least set an object name Change-Id: Ib429a9b246d9d6b4b4cfb11593e4f358850677f2 Reviewed-by: Lars Knoll --- src/network/access/qnetworkreplyhttpimpl.cpp | 2 ++ src/network/bearer/qnetworkconfigmanager_p.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index a4413cda95..2124395de3 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -607,12 +607,14 @@ void QNetworkReplyHttpImplPrivate::postRequest() if (synchronous) { // A synchronous HTTP request uses its own thread thread = new QThread(); + thread->setObjectName(QStringLiteral("httpReply")); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); } else if (!managerPrivate->httpThread) { // We use the manager-global thread. // At some point we could switch to having multiple threads if it makes sense. managerPrivate->httpThread = new QThread(); + managerPrivate->httpThread->setObjectName(QStringLiteral("httpThread")); QObject::connect(managerPrivate->httpThread, SIGNAL(finished()), managerPrivate->httpThread, SLOT(deleteLater())); managerPrivate->httpThread->start(); diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 25bf21e7b9..d152adca92 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -70,6 +70,8 @@ void QNetworkConfigurationManagerPrivate::initialize() { //Two stage construction, because we only want to do this heavyweight work for the winner of the Q_GLOBAL_STATIC race. bearerThread = new QThread(); + bearerThread->setObjectName(QStringLiteral("bearerThread")); + bearerThread->moveToThread(QCoreApplicationPrivate::mainThread()); // because cleanup() is called in main thread context. moveToThread(bearerThread); bearerThread->start(); -- cgit v1.2.3 From 15e136d4e116c1513c106dfbb75e1953a7f3463c Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 2 Mar 2012 19:38:12 +0100 Subject: Mark overload of QAccessible::updateAccessibility as deprecated. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updateAccessibility(const QAccessibleEvent &event) should be used, updateAccessibility(QObject *object, int child, Event reason) is deprecated. Change-Id: I92b32579ff202681189e9581365d2891e5d1e994 Reviewed-by: Jan-Arve Sæther --- src/gui/accessible/qaccessible.cpp | 2 -- src/gui/accessible/qaccessible.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index f256480dc8..b7e9275669 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -650,8 +650,6 @@ void QAccessible::updateAccessibility(QObject *object, int child, Event reason) { Q_ASSERT(object); - qWarning("QAccessible::updateAccessibility is deprecated."); - QAccessibleEvent event = QAccessibleEvent(reason, object, child); updateAccessibility(event); } diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index a72b91a90f..6ad1bb9da9 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -336,7 +336,7 @@ public: static QAccessibleInterface *queryAccessibleInterface(QObject *); - static void updateAccessibility(QObject *object, int child, Event reason); + QT_DEPRECATED static void updateAccessibility(QObject *object, int child, Event reason); static void updateAccessibility(const QAccessibleEvent &event); static bool isActive(); -- cgit v1.2.3 From 95d83cb1b68cc4a415d5d80859b4e74472ad7112 Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Thu, 1 Mar 2012 15:28:31 +0100 Subject: Remove the usage of deprecated qdoc macros. QDoc now has support for Doxygen style commands for italics, bold and list items. This change applies that change in QDoc to the actual documentation. Task-number: QTBUG-24578 Change-Id: I519bf9c29b14092e3ab6067612f42bf749eeedf5 Reviewed-by: Shane Kearns Reviewed-by: Lars Knoll --- doc/src/corelib/containers.qdoc | 196 +-- doc/src/corelib/json.qdoc | 12 +- doc/src/corelib/objectmodel/metaobjects.qdoc | 18 +- doc/src/corelib/objectmodel/object.qdoc | 26 +- doc/src/corelib/objectmodel/properties.qdoc | 22 +- doc/src/corelib/threads-basics.qdoc | 88 +- doc/src/corelib/threads.qdoc | 132 +- doc/src/examples/addressbook.qdoc | 12 +- doc/src/examples/affine.qdoc | 8 +- doc/src/examples/arrowpad.qdoc | 36 +- doc/src/examples/basicdrawing.qdoc | 30 +- doc/src/examples/basicgraphicslayouts.qdoc | 6 +- doc/src/examples/blockingfortuneclient.qdoc | 4 +- doc/src/examples/boxes.qdoc | 6 +- doc/src/examples/cachedtable.qdoc | 8 +- doc/src/examples/calculator.qdoc | 40 +- doc/src/examples/calendar.qdoc | 8 +- doc/src/examples/calendarwidget.qdoc | 40 +- doc/src/examples/charactermap.qdoc | 4 +- doc/src/examples/chart.qdoc | 6 +- doc/src/examples/classwizard.qdoc | 14 +- doc/src/examples/coloreditorfactory.qdoc | 6 +- doc/src/examples/completer.qdoc | 4 +- doc/src/examples/composition.qdoc | 6 +- doc/src/examples/concentriccircles.qdoc | 4 +- doc/src/examples/cube.qdoc | 4 +- doc/src/examples/customsortfiltermodel.qdoc | 4 +- doc/src/examples/dbscreen.qdoc | 26 +- doc/src/examples/diagramscene.qdoc | 20 +- doc/src/examples/drilldown.qdoc | 6 +- doc/src/examples/dropsite.qdoc | 16 +- doc/src/examples/editabletreemodel.qdoc | 40 +- doc/src/examples/elasticnodes.qdoc | 6 +- doc/src/examples/fortuneclient.qdoc | 8 +- doc/src/examples/fridgemagnets.qdoc | 4 +- doc/src/examples/gradients.qdoc | 6 +- doc/src/examples/hellogl.qdoc | 6 +- doc/src/examples/icons.qdoc | 92 +- doc/src/examples/imagecomposition.qdoc | 6 +- doc/src/examples/imageviewer.qdoc | 26 +- doc/src/examples/licensewizard.qdoc | 20 +- doc/src/examples/maemovibration.qdoc | 8 +- doc/src/examples/mandelbrot.qdoc | 16 +- doc/src/examples/mousecalibration.qdoc | 4 +- doc/src/examples/moveblocks.qdoc | 8 +- doc/src/examples/orderform.qdoc | 86 +- doc/src/examples/overpainting.qdoc | 24 +- doc/src/examples/padnavigator.qdoc | 44 +- doc/src/examples/painterpaths.qdoc | 4 +- doc/src/examples/pixelator.qdoc | 4 +- doc/src/examples/plugandpaint.qdoc | 22 +- doc/src/examples/rogue.qdoc | 4 +- doc/src/examples/screenshot.qdoc | 12 +- doc/src/examples/scribble.qdoc | 20 +- doc/src/examples/simpletreemodel.qdoc | 16 +- doc/src/examples/sipdialog.qdoc | 8 +- doc/src/examples/sliders.qdoc | 12 +- doc/src/examples/stardelegate.qdoc | 10 +- doc/src/examples/styles.qdoc | 18 +- doc/src/examples/svgalib.qdoc | 20 +- doc/src/examples/syntaxhighlighter.qdoc | 4 +- doc/src/examples/tablet.qdoc | 8 +- doc/src/examples/tetrix.qdoc | 6 +- doc/src/examples/textfinder.qdoc | 8 +- doc/src/examples/tooltips.qdoc | 4 +- doc/src/examples/transformations.qdoc | 6 +- doc/src/examples/trollprint.qdoc | 30 +- doc/src/examples/undoframework.qdoc | 12 +- doc/src/examples/wiggly.qdoc | 4 +- doc/src/examples/windowflags.qdoc | 4 +- doc/src/gui/coordsys.qdoc | 116 +- doc/src/gui/paintsystem.qdoc | 82 +- .../files-and-resources/datastreamformat.qdoc | 620 ++++---- .../network-programming/bearermanagement.qdoc | 44 +- doc/src/printsupport/printing.qdoc | 16 +- .../sql/sql-programming/qsqldatatype-table.qdoc | 708 ++++----- doc/src/sql/sql-programming/sql-driver.qdoc | 108 +- doc/src/sql/sql-programming/sql-programming.qdoc | 36 +- doc/src/widgets/addressbook-fr.qdoc | 56 +- doc/src/widgets/addressbook.qdoc | 56 +- doc/src/widgets/modelview.qdoc | 580 ++++---- doc/src/widgets/widgets-and-layouts/focus.qdoc | 14 +- .../widgets/widgets-and-layouts/gallery-cde.qdoc | 56 +- .../widgets-and-layouts/gallery-cleanlooks.qdoc | 58 +- .../widgets/widgets-and-layouts/gallery-gtk.qdoc | 58 +- .../widgets-and-layouts/gallery-macintosh.qdoc | 58 +- .../widgets/widgets-and-layouts/gallery-motif.qdoc | 58 +- .../widgets-and-layouts/gallery-plastique.qdoc | 58 +- .../widgets-and-layouts/gallery-windows.qdoc | 58 +- .../widgets-and-layouts/gallery-windowsvista.qdoc | 58 +- .../widgets-and-layouts/gallery-windowsxp.qdoc | 58 +- doc/src/widgets/widgets-and-layouts/gallery.qdoc | 18 +- doc/src/widgets/widgets-and-layouts/layout.qdoc | 62 +- doc/src/widgets/widgets-and-layouts/styles.qdoc | 798 +++++----- .../widgets/widgets-and-layouts/stylesheet.qdoc | 1562 ++++++++++---------- doc/src/widgets/widgets-and-layouts/widgets.qdoc | 32 +- doc/src/widgets/widgets-tutorial.qdoc | 30 +- .../widgets/windows-and-dialogs/mainwindow.qdoc | 10 +- src/concurrent/qtconcurrentexception.cpp | 8 +- src/concurrent/qtconcurrentrun.cpp | 6 +- src/corelib/animation/qvariantanimation.cpp | 24 +- src/corelib/codecs/codecs.qdoc | 56 +- src/corelib/codecs/qtextcodec.cpp | 86 +- src/corelib/global/qglobal.cpp | 14 +- src/corelib/global/qlogging.cpp | 2 +- src/corelib/global/qnamespace.qdoc | 52 +- src/corelib/io/qdatastream.cpp | 28 +- src/corelib/io/qdir.cpp | 20 +- src/corelib/io/qfile.cpp | 8 +- src/corelib/io/qfileinfo.cpp | 6 +- src/corelib/io/qiodevice.cpp | 16 +- src/corelib/io/qprocess.cpp | 18 +- src/corelib/io/qsettings.cpp | 126 +- src/corelib/io/qtextstream.cpp | 68 +- src/corelib/io/qurl.cpp | 16 +- src/corelib/itemmodels/qabstractitemmodel.cpp | 82 +- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 20 +- src/corelib/json/qjsonarray.cpp | 4 +- src/corelib/json/qjsonobject.cpp | 4 +- src/corelib/json/qjsonvalue.cpp | 32 +- src/corelib/kernel/qabstracteventdispatcher.cpp | 24 +- src/corelib/kernel/qcoreapplication.cpp | 10 +- src/corelib/kernel/qeventloop.cpp | 6 +- src/corelib/kernel/qmetaobject.cpp | 26 +- src/corelib/kernel/qmimedata.cpp | 18 +- src/corelib/kernel/qobject.cpp | 28 +- src/corelib/kernel/qpointer.cpp | 4 +- src/corelib/kernel/qsharedmemory.cpp | 6 +- src/corelib/kernel/qsocketnotifier.cpp | 16 +- src/corelib/kernel/qsystemsemaphore.cpp | 8 +- src/corelib/kernel/qtranslator.cpp | 56 +- src/corelib/kernel/qvariant.cpp | 44 +- src/corelib/kernel/qwineventnotifier.cpp | 4 +- src/corelib/plugin/qlibrary.cpp | 12 +- src/corelib/plugin/qpluginloader.cpp | 4 +- src/corelib/plugin/quuid.cpp | 168 +-- src/corelib/thread/qatomic.cpp | 72 +- src/corelib/thread/qsemaphore.cpp | 4 +- src/corelib/thread/qthread.cpp | 4 +- src/corelib/thread/qthreadstorage.cpp | 4 +- src/corelib/thread/qwaitcondition.qdoc | 8 +- src/corelib/tools/qalgorithms.qdoc | 14 +- src/corelib/tools/qbytearray.cpp | 26 +- src/corelib/tools/qdatetime.cpp | 406 ++--- src/corelib/tools/qhash.cpp | 6 +- src/corelib/tools/qline.cpp | 20 +- src/corelib/tools/qlinkedlist.cpp | 6 +- src/corelib/tools/qlist.cpp | 6 +- src/corelib/tools/qlocale.cpp | 22 +- src/corelib/tools/qlocale.qdoc | 12 +- src/corelib/tools/qmap.cpp | 6 +- src/corelib/tools/qrect.cpp | 48 +- src/corelib/tools/qregexp.cpp | 372 ++--- src/corelib/tools/qscopedpointer.cpp | 6 +- src/corelib/tools/qshareddata.cpp | 4 +- src/corelib/tools/qsize.cpp | 12 +- src/corelib/tools/qstring.cpp | 32 +- src/corelib/tools/qstringlist.cpp | 2 +- src/corelib/tools/qvarlengtharray.qdoc | 6 +- src/corelib/tools/qvector.cpp | 8 +- src/dbus/qdbusmessage.cpp | 8 +- src/dbus/qdbuspendingreply.cpp | 4 +- src/dbus/qdbusservicewatcher.cpp | 6 +- src/dbus/qdbusutil.cpp | 24 +- src/gui/accessible/qaccessible.cpp | 10 +- src/gui/accessible/qaccessible2.cpp | 16 +- src/gui/image/qimage.cpp | 84 +- src/gui/image/qimagereader.cpp | 34 +- src/gui/image/qimagewriter.cpp | 16 +- src/gui/image/qpixmap.cpp | 42 +- src/gui/kernel/qclipboard.cpp | 12 +- src/gui/kernel/qcursor.cpp | 98 +- src/gui/kernel/qdrag.cpp | 10 +- src/gui/kernel/qevent.cpp | 44 +- src/gui/kernel/qguiapplication.cpp | 42 +- src/gui/kernel/qkeysequence.cpp | 140 +- src/gui/kernel/qpalette.cpp | 6 +- src/gui/kernel/qplatformnativeinterface_qpa.cpp | 2 +- src/gui/math3d/qgenericmatrix.cpp | 6 +- src/gui/math3d/qmatrix4x4.cpp | 6 +- src/gui/math3d/qvector2d.cpp | 2 +- src/gui/math3d/qvector3d.cpp | 2 +- src/gui/math3d/qvector4d.cpp | 2 +- src/gui/opengl/qopenglframebufferobject.cpp | 10 +- src/gui/painting/qbrush.cpp | 74 +- src/gui/painting/qcolor.cpp | 26 +- src/gui/painting/qmatrix.cpp | 12 +- src/gui/painting/qpainter.cpp | 272 ++-- src/gui/painting/qpainterpath.cpp | 60 +- src/gui/painting/qpen.cpp | 60 +- src/gui/painting/qregion.cpp | 8 +- src/gui/painting/qtransform.cpp | 12 +- src/gui/text/qabstracttextdocumentlayout.cpp | 20 +- src/gui/text/qfont.cpp | 76 +- src/gui/text/qfontdatabase.cpp | 2 +- src/gui/text/qfontmetrics.cpp | 78 +- src/gui/text/qrawfont.cpp | 6 +- src/gui/text/qtextcursor.cpp | 10 +- src/gui/text/qtextdocument.cpp | 14 +- src/gui/text/qtextdocumentwriter.cpp | 8 +- src/gui/text/qtextlist.cpp | 2 +- src/gui/text/qtexttable.cpp | 12 +- src/gui/util/qvalidator.cpp | 16 +- src/network/access/qnetworkaccessmanager.cpp | 8 +- src/network/bearer/qnetworkconfiguration.cpp | 42 +- src/network/bearer/qnetworksession.cpp | 18 +- src/network/kernel/qauthenticator.cpp | 14 +- src/network/kernel/qhostaddress.cpp | 14 +- src/network/kernel/qnetworkproxy.cpp | 66 +- src/network/kernel/qnetworkproxy_mac.cpp | 16 +- src/network/socket/qabstractsocket.cpp | 34 +- src/network/socket/qtcpsocket.cpp | 2 +- src/network/ssl/qsslcertificateextension.cpp | 54 +- src/network/ssl/qsslconfiguration.cpp | 20 +- src/network/ssl/qsslsocket.cpp | 10 +- src/opengl/qgl.cpp | 110 +- src/opengl/qglframebufferobject.cpp | 18 +- src/opengl/qglpixelbuffer.cpp | 6 +- src/plugins/platforms/windows/main.cpp | 6 +- .../platforms/windows/qwindowsdialoghelpers.cpp | 4 +- .../platforms/windows/qwindowsinputcontext.cpp | 8 +- .../platforms/windows/qwindowsintegration.cpp | 6 +- src/plugins/platforms/windows/qwindowsmime.cpp | 14 +- src/plugins/platforms/windows/qwindowsole.cpp | 10 +- src/plugins/platforms/windows/qwindowswindow.cpp | 16 +- src/printsupport/dialogs/qabstractprintdialog.cpp | 4 +- src/printsupport/dialogs/qprintpreviewdialog.cpp | 6 +- src/printsupport/kernel/qprinter.cpp | 10 +- src/printsupport/widgets/qprintpreviewwidget.cpp | 4 +- src/sql/kernel/qsqldatabase.cpp | 174 +-- src/sql/kernel/qsqldriver.cpp | 8 +- src/sql/kernel/qsqlquery.cpp | 44 +- src/sql/models/qsqlrelationaltablemodel.cpp | 14 +- src/testlib/qsignalspy.qdoc | 2 +- src/testlib/qtestcase.cpp | 40 +- src/widgets/dialogs/qdialog.cpp | 4 +- src/widgets/dialogs/qfiledialog.cpp | 2 +- src/widgets/dialogs/qfilesystemmodel.cpp | 8 +- src/widgets/dialogs/qinputdialog.cpp | 8 +- src/widgets/dialogs/qmessagebox.cpp | 164 +- src/widgets/dialogs/qprogressdialog.cpp | 8 +- src/widgets/dialogs/qwizard.cpp | 94 +- src/widgets/effects/qgraphicseffect.cpp | 18 +- src/widgets/graphicsview/qgraphicsanchorlayout.cpp | 6 +- src/widgets/graphicsview/qgraphicsitem.cpp | 72 +- src/widgets/graphicsview/qgraphicslayout.cpp | 22 +- src/widgets/graphicsview/qgraphicsproxywidget.cpp | 68 +- src/widgets/graphicsview/qgraphicsscene.cpp | 6 +- src/widgets/graphicsview/qgraphicswidget.cpp | 154 +- src/widgets/itemviews/qabstractitemview.cpp | 38 +- src/widgets/itemviews/qdatawidgetmapper.cpp | 32 +- src/widgets/itemviews/qdirmodel.cpp | 10 +- src/widgets/itemviews/qitemdelegate.cpp | 52 +- src/widgets/itemviews/qitemeditorfactory.cpp | 22 +- src/widgets/itemviews/qlistview.cpp | 12 +- src/widgets/itemviews/qlistwidget.cpp | 12 +- src/widgets/itemviews/qstyleditemdelegate.cpp | 52 +- src/widgets/itemviews/qtableview.cpp | 16 +- src/widgets/itemviews/qtablewidget.cpp | 12 +- src/widgets/itemviews/qtreeview.cpp | 40 +- src/widgets/itemviews/qtreewidget.cpp | 14 +- src/widgets/kernel/qapplication.cpp | 92 +- src/widgets/kernel/qboxlayout.cpp | 12 +- src/widgets/kernel/qformlayout.cpp | 34 +- src/widgets/kernel/qicon.cpp | 4 +- src/widgets/kernel/qiconengineplugin.cpp | 2 +- src/widgets/kernel/qlayout.cpp | 4 +- src/widgets/kernel/qlayoutitem.cpp | 30 +- src/widgets/kernel/qwidget.cpp | 132 +- src/widgets/kernel/qwidgetaction.cpp | 10 +- src/widgets/styles/qmacstyle.qdoc | 6 +- src/widgets/styles/qstyle.cpp | 342 ++--- src/widgets/styles/qstyleoption.cpp | 8 +- src/widgets/util/qcompleter.cpp | 2 +- src/widgets/util/qscrollerproperties.cpp | 2 +- src/widgets/util/qsystemtrayicon.cpp | 6 +- src/widgets/util/qundostack.cpp | 8 +- src/widgets/widgets/qabstractbutton.cpp | 18 +- src/widgets/widgets/qabstractscrollarea.cpp | 8 +- src/widgets/widgets/qabstractslider.cpp | 40 +- src/widgets/widgets/qabstractspinbox.cpp | 28 +- src/widgets/widgets/qcalendarwidget.cpp | 16 +- src/widgets/widgets/qcheckbox.cpp | 16 +- src/widgets/widgets/qdatetimeedit.cpp | 60 +- src/widgets/widgets/qdial.cpp | 8 +- src/widgets/widgets/qdialogbuttonbox.cpp | 42 +- src/widgets/widgets/qdockwidget.cpp | 8 +- src/widgets/widgets/qframe.cpp | 6 +- src/widgets/widgets/qgroupbox.cpp | 20 +- src/widgets/widgets/qlabel.cpp | 48 +- src/widgets/widgets/qlcdnumber.cpp | 18 +- src/widgets/widgets/qlineedit.cpp | 104 +- src/widgets/widgets/qmainwindow.cpp | 8 +- src/widgets/widgets/qmdiarea.cpp | 4 +- src/widgets/widgets/qmenu.cpp | 8 +- src/widgets/widgets/qmenubar.cpp | 32 +- src/widgets/widgets/qplaintextedit.cpp | 82 +- src/widgets/widgets/qprogressbar.cpp | 12 +- src/widgets/widgets/qpushbutton.cpp | 30 +- src/widgets/widgets/qradiobutton.cpp | 12 +- src/widgets/widgets/qscrollarea.cpp | 6 +- src/widgets/widgets/qscrollbar.cpp | 50 +- src/widgets/widgets/qsizegrip.cpp | 4 +- src/widgets/widgets/qslider.cpp | 42 +- src/widgets/widgets/qspinbox.cpp | 12 +- src/widgets/widgets/qstackedwidget.cpp | 2 +- src/widgets/widgets/qstatusbar.cpp | 6 +- src/widgets/widgets/qtabbar.cpp | 18 +- src/widgets/widgets/qtabwidget.cpp | 20 +- src/widgets/widgets/qtextbrowser.cpp | 32 +- src/widgets/widgets/qtextedit.cpp | 76 +- src/widgets/widgets/qtoolbutton.cpp | 4 +- src/widgets/widgets/qworkspace.cpp | 4 +- src/xml/dom/qdom.cpp | 114 +- src/xml/sax/qxml.cpp | 72 +- 315 files changed, 7041 insertions(+), 7041 deletions(-) diff --git a/doc/src/corelib/containers.qdoc b/doc/src/corelib/containers.qdoc index e28c3bdbfe..b63cc9df28 100644 --- a/doc/src/corelib/containers.qdoc +++ b/doc/src/corelib/containers.qdoc @@ -104,10 +104,10 @@ efficient hash-lookup of objects in a limited cache storage. \table - \header \o Class \o Summary + \header \li Class \li Summary - \row \o \l{QList} - \o This is by far the most commonly used container class. It + \row \li \l{QList} + \li This is by far the most commonly used container class. It stores a list of values of a given type (T) that can be accessed by index. Internally, the QList is implemented using an array, ensuring that index-based access is very fast. @@ -119,8 +119,8 @@ possible in the executable. QStringList inherits from QList. - \row \o \l{QLinkedList} - \o This is similar to QList, except that it uses + \row \li \l{QLinkedList} + \li This is similar to QList, except that it uses iterators rather than integer indexes to access items. It also provides better performance than QList when inserting in the middle of a huge list, and it has nicer iterator semantics. @@ -128,48 +128,48 @@ long as the item exists, whereas iterators to a QList can become invalid after any insertion or removal.) - \row \o \l{QVector} - \o This stores an array of values of a given type at adjacent + \row \li \l{QVector} + \li This stores an array of values of a given type at adjacent positions in memory. Inserting at the front or in the middle of a vector can be quite slow, because it can lead to large numbers of items having to be moved by one position in memory. - \row \o \l{QStack} - \o This is a convenience subclass of QVector that provides + \row \li \l{QStack} + \li This is a convenience subclass of QVector that provides "last in, first out" (LIFO) semantics. It adds the following functions to those already present in QVector: \l{QStack::push()}{push()}, \l{QStack::pop()}{pop()}, and \l{QStack::top()}{top()}. - \row \o \l{QQueue} - \o This is a convenience subclass of QList that provides + \row \li \l{QQueue} + \li This is a convenience subclass of QList that provides "first in, first out" (FIFO) semantics. It adds the following functions to those already present in QList: \l{QQueue::enqueue()}{enqueue()}, \l{QQueue::dequeue()}{dequeue()}, and \l{QQueue::head()}{head()}. - \row \o \l{QSet} - \o This provides a single-valued mathematical set with fast + \row \li \l{QSet} + \li This provides a single-valued mathematical set with fast lookups. - \row \o \l{QMap} - \o This provides a dictionary (associative array) that maps keys + \row \li \l{QMap} + \li This provides a dictionary (associative array) that maps keys of type Key to values of type T. Normally each key is associated with a single value. QMap stores its data in Key order; if order doesn't matter QHash is a faster alternative. - \row \o \l{QMultiMap} - \o This is a convenience subclass of QMap that provides a nice + \row \li \l{QMultiMap} + \li This is a convenience subclass of QMap that provides a nice interface for multi-valued maps, i.e. maps where one key can be associated with multiple values. - \row \o \l{QHash} - \o This has almost the same API as QMap, but provides + \row \li \l{QHash} + \li This has almost the same API as QMap, but provides significantly faster lookups. QHash stores its data in an arbitrary order. - \row \o \l{QMultiHash} - \o This is a convenience subclass of QHash that + \row \li \l{QMultiHash} + \li This is a convenience subclass of QHash that provides a nice interface for multi-valued hashes. \endtable @@ -271,20 +271,20 @@ read-write access. \table - \header \o Containers \o Read-only iterator - \o Read-write iterator - \row \o QList, QQueue \o QListIterator - \o QMutableListIterator - \row \o QLinkedList \o QLinkedListIterator - \o QMutableLinkedListIterator - \row \o QVector, QStack \o QVectorIterator - \o QMutableVectorIterator - \row \o QSet \o QSetIterator - \o QMutableSetIterator - \row \o QMap, QMultiMap \o QMapIterator - \o QMutableMapIterator - \row \o QHash, QMultiHash \o QHashIterator - \o QMutableHashIterator + \header \li Containers \li Read-only iterator + \li Read-write iterator + \row \li QList, QQueue \li QListIterator + \li QMutableListIterator + \row \li QLinkedList \li QLinkedListIterator + \li QMutableLinkedListIterator + \row \li QVector, QStack \li QVectorIterator + \li QMutableVectorIterator + \row \li QSet \li QSetIterator + \li QMutableSetIterator + \row \li QMap, QMultiMap \li QMapIterator + \li QMutableMapIterator + \row \li QHash, QMultiHash \li QHashIterator + \li QMutableHashIterator \endtable In this discussion, we will concentrate on QList and QMap. The @@ -334,23 +334,23 @@ The following table summarizes the QListIterator API: \table - \header \o Function \o Behavior - \row \o \l{QListIterator::toFront()}{toFront()} - \o Moves the iterator to the front of the list (before the first item) - \row \o \l{QListIterator::toBack()}{toBack()} - \o Moves the iterator to the back of the list (after the last item) - \row \o \l{QListIterator::hasNext()}{hasNext()} - \o Returns true if the iterator isn't at the back of the list - \row \o \l{QListIterator::next()}{next()} - \o Returns the next item and advances the iterator by one position - \row \o \l{QListIterator::peekNext()}{peekNext()} - \o Returns the next item without moving the iterator - \row \o \l{QListIterator::hasPrevious()}{hasPrevious()} - \o Returns true if the iterator isn't at the front of the list - \row \o \l{QListIterator::previous()}{previous()} - \o Returns the previous item and moves the iterator back by one position - \row \o \l{QListIterator::peekPrevious()}{peekPrevious()} - \o Returns the previous item without moving the iterator + \header \li Function \li Behavior + \row \li \l{QListIterator::toFront()}{toFront()} + \li Moves the iterator to the front of the list (before the first item) + \row \li \l{QListIterator::toBack()}{toBack()} + \li Moves the iterator to the back of the list (after the last item) + \row \li \l{QListIterator::hasNext()}{hasNext()} + \li Returns true if the iterator isn't at the back of the list + \row \li \l{QListIterator::next()}{next()} + \li Returns the next item and advances the iterator by one position + \row \li \l{QListIterator::peekNext()}{peekNext()} + \li Returns the next item without moving the iterator + \row \li \l{QListIterator::hasPrevious()}{hasPrevious()} + \li Returns true if the iterator isn't at the front of the list + \row \li \l{QListIterator::previous()}{previous()} + \li Returns the previous item and moves the iterator back by one position + \row \li \l{QListIterator::peekPrevious()}{peekPrevious()} + \li Returns the previous item without moving the iterator \endtable QListIterator provides no functions to insert or remove items @@ -440,20 +440,20 @@ possible because they are faster than read-write iterators. \table - \header \o Containers \o Read-only iterator - \o Read-write iterator - \row \o QList, QQueue \o QList::const_iterator - \o QList::iterator - \row \o QLinkedList \o QLinkedList::const_iterator - \o QLinkedList::iterator - \row \o QVector, QStack \o QVector::const_iterator - \o QVector::iterator - \row \o QSet \o QSet::const_iterator - \o QSet::iterator - \row \o QMap, QMultiMap \o QMap::const_iterator - \o QMap::iterator - \row \o QHash, QMultiHash \o QHash::const_iterator - \o QHash::iterator + \header \li Containers \li Read-only iterator + \li Read-write iterator + \row \li QList, QQueue \li QList::const_iterator + \li QList::iterator + \row \li QLinkedList \li QLinkedList::const_iterator + \li QLinkedList::iterator + \row \li QVector, QStack \li QVector::const_iterator + \li QVector::iterator + \row \li QSet \li QSet::const_iterator + \li QSet::iterator + \row \li QMap, QMultiMap \li QMap::const_iterator + \li QMap::iterator + \row \li QHash, QMultiHash \li QHash::const_iterator + \li QHash::iterator \endtable The API of the STL iterators is modelled on pointers in an array. @@ -509,13 +509,13 @@ The following table summarizes the STL-style iterators' API: \table - \header \o Expression \o Behavior - \row \o \c{*i} \o Returns the current item - \row \o \c{++i} \o Advances the iterator to the next item - \row \o \c{i += n} \o Advances the iterator by \c n items - \row \o \c{--i} \o Moves the iterator back by one item - \row \o \c{i -= n} \o Moves the iterator back by \c n items - \row \o \c{i - j} \o Returns the number of items between iterators \c i and \c j + \header \li Expression \li Behavior + \row \li \c{*i} \li Returns the current item + \row \li \c{++i} \li Advances the iterator to the next item + \row \li \c{i += n} \li Advances the iterator by \c n items + \row \li \c{--i} \li Moves the iterator back by one item + \row \li \c{i -= n} \li Moves the iterator back by \c n items + \row \li \c{i - j} \li Returns the number of items between iterators \c i and \c j \endtable The \c{++} and \c{--} operators are available both as prefix @@ -625,17 +625,17 @@ be used with the \c foreach keyword. \list - \o QVarLengthArray provides a low-level + \li QVarLengthArray provides a low-level variable-length array. It can be used instead of QVector in places where speed is particularly important. - \o QCache provides a cache to store objects of a certain + \li QCache provides a cache to store objects of a certain type T associated with keys of type Key. - \o QContiguousCache provides an efficient way of caching data + \li QContiguousCache provides an efficient way of caching data that is typically accessed in a contiguous way. - \o QPair stores a pair of elements. + \li QPair stores a pair of elements. \endlist Additional non-template types that compete with Qt's template @@ -662,27 +662,27 @@ \keyword quadratic time \list - \o \bold{Constant time:} O(1). A function is said to run in constant + \li \b{Constant time:} O(1). A function is said to run in constant time if it requires the same amount of time no matter how many items are present in the container. One example is QLinkedList::insert(). - \o \bold{Logarithmic time:} O(log \e n). A function that runs in + \li \b{Logarithmic time:} O(log \e n). A function that runs in logarithmic time is a function whose running time is proportional to the logarithm of the number of items in the container. One example is qBinaryFind(). - \o \bold{Linear time:} O(\e n). A function that runs in linear time + \li \b{Linear time:} O(\e n). A function that runs in linear time will execute in a time directly proportional to the number of items stored in the container. One example is QVector::insert(). - \o \bold{Linear-logarithmic time:} O(\e{n} log \e n). A function + \li \b{Linear-logarithmic time:} O(\e{n} log \e n). A function that runs in linear-logarithmic time is asymptotically slower than a linear-time function, but faster than a quadratic-time function. - \o \bold{Quadratic time:} O(\e{n}\unicode{178}). A quadratic-time function + \li \b{Quadratic time:} O(\e{n}\unicode{178}). A quadratic-time function executes in a time that is proportional to the square of the number of items stored in the container. \endlist @@ -691,10 +691,10 @@ sequential container classes: \table - \header \o \o Index lookup \o Insertion \o Prepending \o Appending - \row \o QLinkedList \o O(\e n) \o O(1) \o O(1) \o O(1) - \row \o QList \o O(1) \o O(n) \o Amort. O(1) \o Amort. O(1) - \row \o QVector \o O(1) \o O(n) \o O(n) \o Amort. O(1) + \header \li \li Index lookup \li Insertion \li Prepending \li Appending + \row \li QLinkedList \li O(\e n) \li O(1) \li O(1) \li O(1) + \row \li QList \li O(1) \li O(n) \li Amort. O(1) \li Amort. O(1) + \row \li QVector \li O(1) \li O(n) \li O(n) \li Amort. O(1) \endtable In the table, "Amort." stands for "amortized behavior". For @@ -707,12 +707,12 @@ associative containers and sets: \table - \header \o{1,2} \o{2,1} Key lookup \o{2,1} Insertion - \header \o Average \o Worst case \o Average \o Worst case - \row \o QMap \o O(log \e n) \o O(log \e n) \o O(log \e n) \o O(log \e n) - \row \o QMultiMap \o O(log \e n) \o O(log \e n) \o O(log \e n) \o O(log \e n) - \row \o QHash \o Amort. O(1) \o O(\e n) \o Amort. O(1) \o O(\e n) - \row \o QSet \o Amort. O(1) \o O(\e n) \o Amort. O(1) \o O(\e n) + \header \li{1,2} \li{2,1} Key lookup \li{2,1} Insertion + \header \li Average \li Worst case \li Average \li Worst case + \row \li QMap \li O(log \e n) \li O(log \e n) \li O(log \e n) \li O(log \e n) + \row \li QMultiMap \li O(log \e n) \li O(log \e n) \li O(log \e n) \li O(log \e n) + \row \li QHash \li Amort. O(1) \li O(\e n) \li Amort. O(1) \li O(\e n) + \row \li QSet \li Amort. O(1) \li O(\e n) \li Amort. O(1) \li O(\e n) \endtable With QVector, QHash, and QSet, the performance of appending items @@ -749,13 +749,13 @@ The values above may seem a bit strange, but here are the guiding principles: \list - \o QString allocates 4 characters at a time until it reaches size 20. - \o From 20 to 4084, it advances by doubling the size each time. + \li QString allocates 4 characters at a time until it reaches size 20. + \li From 20 to 4084, it advances by doubling the size each time. More precisely, it advances to the next power of two, minus 12. (Some memory allocators perform worst when requested exact powers of two, because they use a few bytes per block for book-keeping.) - \o From 4084 on, it advances by blocks of 2048 characters (4096 + \li From 4084 on, it advances by blocks of 2048 characters (4096 bytes). This makes sense because modern operating systems don't copy the entire data when reallocating a buffer; the physical memory pages are simply reordered, and only the data @@ -787,12 +787,12 @@ use to store the items: \list - \o \l{QString::capacity()}{capacity()} returns the + \li \l{QString::capacity()}{capacity()} returns the number of items for which memory is allocated (for QHash and QSet, the number of buckets in the hash table). - \o \l{QString::reserve()}{reserve}(\e size) explicitly + \li \l{QString::reserve()}{reserve}(\e size) explicitly preallocates memory for \e size items. - \o \l{QString::squeeze()}{squeeze()} frees any memory + \li \l{QString::squeeze()}{squeeze()} frees any memory not required to store the items. \endlist diff --git a/doc/src/corelib/json.qdoc b/doc/src/corelib/json.qdoc index 91a89761e3..88b5377074 100644 --- a/doc/src/corelib/json.qdoc +++ b/doc/src/corelib/json.qdoc @@ -59,12 +59,12 @@ JSON is a format to store structured data. It has 6 basic data types: \list - \o bool - \o double - \o string - \o array - \o object - \o null + \li bool + \li double + \li string + \li array + \li object + \li null \endlist Any value can be any of the above type. A boolean value is represented by the diff --git a/doc/src/corelib/objectmodel/metaobjects.qdoc b/doc/src/corelib/objectmodel/metaobjects.qdoc index 7edb376e25..c92f6f2f09 100644 --- a/doc/src/corelib/objectmodel/metaobjects.qdoc +++ b/doc/src/corelib/objectmodel/metaobjects.qdoc @@ -41,12 +41,12 @@ The meta-object system is based on three things: \list 1 - \o The \l QObject class provides a base class for objects that can + \li The \l QObject class provides a base class for objects that can take advantage of the meta-object system. - \o The Q_OBJECT macro inside the private section of the class + \li The Q_OBJECT macro inside the private section of the class declaration is used to enable meta-object features, such as dynamic properties, signals, and slots. - \o The \l{moc}{Meta-Object Compiler} (\c moc) supplies each + \li The \l{moc}{Meta-Object Compiler} (\c moc) supplies each QObject subclass with the necessary code to implement meta-object features. \endlist @@ -64,19 +64,19 @@ additional features: \list - \o QObject::metaObject() returns the associated + \li QObject::metaObject() returns the associated \l{QMetaObject}{meta-object} for the class. - \o QMetaObject::className() returns the class name as a + \li QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler. - \o QObject::inherits() function returns whether an object is an + \li QObject::inherits() function returns whether an object is an instance of a class that inherits a specified class within the QObject inheritance tree. - \o QObject::tr() and QObject::trUtf8() translate strings for + \li QObject::tr() and QObject::trUtf8() translate strings for \l{Internationalization with Qt}{internationalization}. - \o QObject::setProperty() and QObject::property() + \li QObject::setProperty() and QObject::property() dynamically set and get properties by name. - \o QMetaObject::newInstance() constructs a new instance of the class. + \li QMetaObject::newInstance() constructs a new instance of the class. \endlist \target qobjectcast diff --git a/doc/src/corelib/objectmodel/object.qdoc b/doc/src/corelib/objectmodel/object.qdoc index cf3ce4ef31..4e212b37dd 100644 --- a/doc/src/corelib/objectmodel/object.qdoc +++ b/doc/src/corelib/objectmodel/object.qdoc @@ -41,20 +41,20 @@ Qt adds these features to C++: \list - \o a very powerful mechanism for seamless object + \li a very powerful mechanism for seamless object communication called \l{signals and slots} - \o queryable and designable \l{Qt's Property System}{object + \li queryable and designable \l{Qt's Property System}{object properties} - \o powerful \l{The Event System}{events and event filters} - \o contextual \l{i18n}{string translation for internationalization} - \o sophisticated interval driven \l timers that make it possible + \li powerful \l{The Event System}{events and event filters} + \li contextual \l{i18n}{string translation for internationalization} + \li sophisticated interval driven \l timers that make it possible to elegantly integrate many tasks in an event-driven GUI - \o hierarchical and queryable \l{Object Trees & Ownership}{object + \li hierarchical and queryable \l{Object Trees & Ownership}{object trees} that organize object ownership in a natural way - \o guarded pointers (QPointer) that are automatically + \li guarded pointers (QPointer) that are automatically set to 0 when the referenced object is destroyed, unlike normal C++ pointers which become dangling pointers when their objects are destroyed - \o a \l{metaobjects.html#qobjectcast}{dynamic cast} that works across + \li a \l{metaobjects.html#qobjectcast}{dynamic cast} that works across library boundaries. \endlist @@ -92,22 +92,22 @@ or assigning a value. We can see what this means in the Qt Object Model. - \bold{A Qt Object...} + \b{A Qt Object...} \list - \o might have a unique \l{QObject::objectName()}. If we copy a Qt + \li might have a unique \l{QObject::objectName()}. If we copy a Qt Object, what name should we give the copy? - \o has a location in an \l{Object Trees & Ownership} + \li has a location in an \l{Object Trees & Ownership} {object hierarchy}. If we copy a Qt Object, where should the copy be located? - \o can be connected to other Qt Objects to emit signals to them or + \li can be connected to other Qt Objects to emit signals to them or to receive signals emitted by them. If we copy a Qt Object, how should we transfer these connections to the copy? - \o can have \l{Qt's Property System} {new properties} added to it + \li can have \l{Qt's Property System} {new properties} added to it at runtime that are not declared in the C++ class. If we copy a Qt Object, should the copy include the properties that were added to the original? diff --git a/doc/src/corelib/objectmodel/properties.qdoc b/doc/src/corelib/objectmodel/properties.qdoc index 894efd017d..4d090af8fc 100644 --- a/doc/src/corelib/objectmodel/properties.qdoc +++ b/doc/src/corelib/objectmodel/properties.qdoc @@ -58,20 +58,20 @@ \list - \o A \c READ accessor function is required. It is for reading the + \li A \c READ accessor function is required. It is for reading the property value. Ideally, a const function is used for this purpose, and it must return either the property's type or a pointer or reference to that type. e.g., QWidget::focus is a read-only property with \c READ function, QWidget::hasFocus(). - \o A \c WRITE accessor function is optional. It is for setting the + \li A \c WRITE accessor function is optional. It is for setting the property value. It must return void and must take exactly one argument, either of the property's type or a pointer or reference to that type. e.g., QWidget::enabled has the \c WRITE function QWidget::setEnabled(). Read-only properties do not need \c WRITE functions. e.g., QWidget::focus has no \c WRITE function. - \o A \c RESET function is optional. It is for setting the property + \li A \c RESET function is optional. It is for setting the property back to its context specific default value. e.g., QWidget::cursor has the typical \c READ and \c WRITE functions, QWidget::cursor() and QWidget::setCursor(), and it also has a \c RESET function, @@ -79,26 +79,26 @@ mean \e {reset to the context specific cursor}. The \c RESET function must return void and take no parameters. - \o A \c NOTIFY signal is optional. If defined, it should specify one + \li A \c NOTIFY signal is optional. If defined, it should specify one existing signal in that class that is emitted whenever the value of the property changes. - \o A \c REVISION number is optional. If included, it defines the + \li A \c REVISION number is optional. If included, it defines the the property and its notifier signal to be used in a particular revision of the API that is exposed to QML. - \o The \c DESIGNABLE attribute indicates whether the property + \li The \c DESIGNABLE attribute indicates whether the property should be visible in the property editor of GUI design tool (e.g., \l {Qt Designer}). Most properties are \c DESIGNABLE (default true). Instead of true or false, you can specify a boolean member function. - \o The \c SCRIPTABLE attribute indicates whether this property + \li The \c SCRIPTABLE attribute indicates whether this property should be accessible by a scripting engine (default true). Instead of true or false, you can specify a boolean member function. - \o The \c STORED attribute indicates whether the property should + \li The \c STORED attribute indicates whether the property should be thought of as existing on its own or as depending on other values. It also indicates whether the property value must be saved when storing the object's state. Most properties are \c STORED @@ -106,20 +106,20 @@ false, because its value is just taken from the width component of property QWidget::minimumSize(), which is a QSize. - \o The \c USER attribute indicates whether the property is + \li The \c USER attribute indicates whether the property is designated as the user-facing or user-editable property for the class. Normally, there is only one \c USER property per class (default false). e.g., QAbstractButton::checked is the user editable property for (checkable) buttons. Note that QItemDelegate gets and sets a widget's \c USER property. - \o The presence of the \c CONSTANT attibute indicates that the property + \li The presence of the \c CONSTANT attibute indicates that the property value is constant. For a given object instance, the READ method of a constant property must return the same value every time it is called. This constant value may be different for different instances of the object. A constant property cannot have a WRITE method or a NOTIFY signal. - \o The presence of the \c FINAL attribute indicates that the property + \li The presence of the \c FINAL attribute indicates that the property will not be overridden by a derived class. This can be used for performance optimizations in some cases, but is not enforced by moc. Care must be taken never to override a \c FINAL property. diff --git a/doc/src/corelib/threads-basics.qdoc b/doc/src/corelib/threads-basics.qdoc index 44a3961177..e54f8a7ccb 100644 --- a/doc/src/corelib/threads-basics.qdoc +++ b/doc/src/corelib/threads-basics.qdoc @@ -123,8 +123,8 @@ There are basically two use cases for threads: \list - \o Make processing faster by making use of multicore processors. - \o Keep the GUI thread or other time critical threads responsive by + \li Make processing faster by making use of multicore processors. + \li Keep the GUI thread or other time critical threads responsive by offloading long lasting processing or blocking calls to other threads. \endlist @@ -138,23 +138,23 @@ \table \header - \o Alternative - \o Comment + \li Alternative + \li Comment \row - \o QEventLoop::processEvents() - \o Calling QEventLoop::processEvents() repeatedly during a + \li QEventLoop::processEvents() + \li Calling QEventLoop::processEvents() repeatedly during a time-consuming calculation prevents GUI blocking. However, this solution doesn't scale well because the call to processEvents() may occur too often, or not often enough, depending on hardware. \row - \o QTimer - \o Background processing can sometimes be done conveniently using a + \li QTimer + \li Background processing can sometimes be done conveniently using a timer to schedule execution of a slot at some point in the future. A timer with an interval of 0 will time out as soon as there are no more events to process. \row - \o QSocketNotifier QNetworkAccessManager QIODevice::readyRead() - \o This is an alternative to having one or multiple threads, each with + \li QSocketNotifier QNetworkAccessManager QIODevice::readyRead() + \li This is an alternative to having one or multiple threads, each with a blocking read on a slow network connection. As long as the calculation in response to a chunk of network data can be executed quickly, this reactive design is better than synchronous waiting in @@ -183,55 +183,55 @@ \table \header - \o Lifetime of thread - \o Development task - \o Solution + \li Lifetime of thread + \li Development task + \li Solution \row - \o One call - \o Run one method within another thread and quit the thread when the + \li One call + \li Run one method within another thread and quit the thread when the method is finished. - \o Qt provides different solutions: + \li Qt provides different solutions: \list - \o Write a function and run it with QtConcurrent::run() - \o Derive a class from QRunnable and run it in the global thread + \li Write a function and run it with QtConcurrent::run() + \li Derive a class from QRunnable and run it in the global thread pool with QThreadPool::globalInstance()->start() - \o Derive a class from QThread, reimplement the QThread::run() + \li Derive a class from QThread, reimplement the QThread::run() method and use QThread::start() to run it. \endlist \row - \o One call - \o Operations are to be performed on all items of a container. + \li One call + \li Operations are to be performed on all items of a container. Processing should be performed using all available cores. A common example is to produce thumbnails from a list of images. - \o QtConcurrent provides the \l{QtConcurrent::}{map()} function for + \li QtConcurrent provides the \l{QtConcurrent::}{map()} function for applying operations on every container element, \l{QtConcurrent::}{filter()} for selecting container elements, and the option of specifying a reduce function for combining the remaining elements. \row - \o One call - \o A long running operation has to be put in another thread. During the + \li One call + \li A long running operation has to be put in another thread. During the course of processing, status information should be sent to the GUI thread. - \o Use QThread, reimplement run and emit signals as needed. Connect the + \li Use QThread, reimplement run and emit signals as needed. Connect the signals to the GUI thread's slots using queued signal/slot connections. \row - \o Permanent - \o Have an object living in another thread and let it perform different + \li Permanent + \li Have an object living in another thread and let it perform different tasks upon request. This means communication to and from the worker thread is required. - \o Derive a class from QObject and implement the necessary slots and + \li Derive a class from QObject and implement the necessary slots and signals, move the object to a thread with a running event loop and communicate with the object over queued signal/slot connections. \row - \o Permanent - \o Have an object living in another thread, let the object perform + \li Permanent + \li Have an object living in another thread, let the object perform repeated tasks such as polling a port and enable communication with the GUI thread. - \o Same as above but also use a timer in the worker thread to implement + \li Same as above but also use a timer in the worker thread to implement polling. However, the best solution for polling is to avoid it completely. Sometimes using QSocketNotifier is an alternative. \endtable @@ -304,18 +304,18 @@ The anatomy of QThread is quite interesting: \list - \o QThread does not live in the new thread where \l{QThread::}{run()} is + \li QThread does not live in the new thread where \l{QThread::}{run()} is executed. It lives in the old thread. - \o Most QThread methods are the thread's control interface and are meant to + \li Most QThread methods are the thread's control interface and are meant to be called from the old thread. Do not move this interface to the newly created thread using \l{QObject::}{moveToThread()}; i.e., calling \l{QObject::moveToThread()}{moveToThread(this)} is regarded as bad practice. - \o \l{QThread::}{exec()} and the static methods + \li \l{QThread::}{exec()} and the static methods \l{QThread::}{usleep()}, \l{QThread::}{msleep()}, \l{QThread::}{sleep()} are meant to be called from the newly created thread. - \o Additional members defined in the QThread subclass are + \li Additional members defined in the QThread subclass are accessible by both threads. The developer is responsible for coordinating access. A typical strategy is to set the members before \l{QThread::}{start()} is called. Once the worker thread is running, @@ -432,11 +432,11 @@ main thread. \list - \o Using QThread as shown \l{Qt thread basics}{above} - \o \l{Example 1: Using the Thread Pool}{Using the global QThreadPool} - \o \l{Example 2: Using QtConcurrent}{Using QtConcurrent} - \o \l{Example 3: Clock}{Communication with the GUI thread} - \o \l{Example 4: A Permanent Thread}{A permanent QObject in another thread + \li Using QThread as shown \l{Qt thread basics}{above} + \li \l{Example 1: Using the Thread Pool}{Using the global QThreadPool} + \li \l{Example 2: Using QtConcurrent}{Using QtConcurrent} + \li \l{Example 3: Clock}{Communication with the GUI thread} + \li \l{Example 4: A Permanent Thread}{A permanent QObject in another thread provides service to the main thread} \endlist @@ -558,13 +558,13 @@ can help you go into the subject in more depth: \list - \o Good video tutorials about threads with Qt can be found in the material + \li Good video tutorials about threads with Qt can be found in the material from the \l{Training Day at Qt Developer Days 2009}. - \o The \l{Thread Support in Qt} document is a good starting point into + \li The \l{Thread Support in Qt} document is a good starting point into the reference documentation. - \o Qt comes with several additional examples for + \li Qt comes with several additional examples for \l{Threading and Concurrent Programming Examples}{QThread and QtConcurrent}. - \o Several good books describe how to work with Qt threads. The most + \li Several good books describe how to work with Qt threads. The most extensive coverage can be found in \e{Advanced Qt Programming} by Mark Summerfield, Prentice Hall - roughly 70 of 500 pages cover QThread and QtConcurrent. diff --git a/doc/src/corelib/threads.qdoc b/doc/src/corelib/threads.qdoc index 3b4def4174..04a5379b2d 100644 --- a/doc/src/corelib/threads.qdoc +++ b/doc/src/corelib/threads.qdoc @@ -54,14 +54,14 @@ \section1 Topics: \list - \o \l{Recommended Reading} - \o \l{The Threading Classes} - \o \l{Starting Threads with QThread} - \o \l{Synchronizing Threads} - \o \l{Reentrancy and Thread-Safety} - \o \l{Threads and QObjects} - \o \l{Concurrent Programming} - \o \l{Thread-Support in Qt Modules} + \li \l{Recommended Reading} + \li \l{The Threading Classes} + \li \l{Starting Threads with QThread} + \li \l{Synchronizing Threads} + \li \l{Reentrancy and Thread-Safety} + \li \l{Threads and QObjects} + \li \l{Concurrent Programming} + \li \l{Thread-Support in Qt Modules} \endlist \section1 Recommended Reading @@ -71,10 +71,10 @@ to threading see our Recommended Reading list: \list - \o \l{Threads Primer: A Guide to Multithreaded Programming} - \o \l{Thread Time: The Multithreaded Programming Guide} - \o \l{Pthreads Programming: A POSIX Standard for Better Multiprocessing} - \o \l{Win32 Multithreaded Programming} + \li \l{Threads Primer: A Guide to Multithreaded Programming} + \li \l{Thread Time: The Multithreaded Programming Guide} + \li \l{Pthreads Programming: A POSIX Standard for Better Multiprocessing} + \li \l{Win32 Multithreaded Programming} \endlist \section1 The Threading Classes @@ -85,21 +85,21 @@ \omit \list - \o QThread provides the means to start a new thread. - \o QThreadStorage provides per-thread data storage. - \o QThreadPool manages a pool of threads that run QRunnable objects. - \o QRunnable is an abstract class representing a runnable object. - \o QMutex provides a mutual exclusion lock, or mutex. - \o QMutexLocker is a convenience class that automatically locks + \li QThread provides the means to start a new thread. + \li QThreadStorage provides per-thread data storage. + \li QThreadPool manages a pool of threads that run QRunnable objects. + \li QRunnable is an abstract class representing a runnable object. + \li QMutex provides a mutual exclusion lock, or mutex. + \li QMutexLocker is a convenience class that automatically locks and unlocks a QMutex. - \o QReadWriteLock provides a lock that allows simultaneous read access. - \o QReadLocker and QWriteLocker are convenience classes that automatically + \li QReadWriteLock provides a lock that allows simultaneous read access. + \li QReadLocker and QWriteLocker are convenience classes that automatically lock and unlock a QReadWriteLock. - \o QSemaphore provides an integer semaphore (a generalization of a mutex). - \o QWaitCondition provides a way for threads to go to sleep until + \li QSemaphore provides an integer semaphore (a generalization of a mutex). + \li QWaitCondition provides a way for threads to go to sleep until woken up by another thread. - \o QAtomicInt provides atomic operations on integers. - \o QAtomicPointer provides atomic operations on pointers. + \li QAtomicInt provides atomic operations on integers. + \li QAtomicPointer provides atomic operations on pointers. \endlist \endomit @@ -226,10 +226,10 @@ how they can be used in multithread applications: \list - \o A \e thread-safe function can be called simultaneously from + \li A \e thread-safe function can be called simultaneously from multiple threads, even when the invocations use shared data, because all references to the shared data are serialized. - \o A \e reentrant function can also be called simultaneously from + \li A \e reentrant function can also be called simultaneously from multiple threads, but only if each invocation uses its own data. \endlist @@ -267,9 +267,9 @@ Indeed, they usually expand to three machine instructions: \list 1 - \o Load the variable's value in a register. - \o Increment or decrement the register's value. - \o Store the register's value back into main memory. + \li Load the variable's value in a register. + \li Increment or decrement the register's value. + \li Store the register's value back into main memory. \endlist If thread A and thread B load the variable's old value @@ -346,19 +346,19 @@ guaranteed to work. There are three constraints to be aware of: \list - \o \e{The child of a QObject must always be created in the thread + \li \e{The child of a QObject must always be created in the thread where the parent was created.} This implies, among other things, that you should never pass the QThread object (\c this) as the parent of an object created in the thread (since the QThread object itself was created in another thread). - \o \e{Event driven objects may only be used in a single thread.} + \li \e{Event driven objects may only be used in a single thread.} Specifically, this applies to the \l{timers.html}{timer mechanism} and the \l{QtNetwork}{network module}. For example, you cannot start a timer or connect a socket in a thread that is not the \l{QObject::thread()}{object's thread}. - \o \e{You must ensure that all objects created in a thread are + \li \e{You must ensure that all objects created in a thread are deleted before you delete the QThread.} This can be done easily by creating the objects on the stack in your \l{QThread::run()}{run()} implementation. @@ -469,26 +469,26 @@ \list - \o \l{Qt::AutoConnection}{Auto Connection} (default) If the signal is + \li \l{Qt::AutoConnection}{Auto Connection} (default) If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection." - \o \l{Qt::DirectConnection}{Direct Connection} The slot is invoked + \li \l{Qt::DirectConnection}{Direct Connection} The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread. - \o \l{Qt::QueuedConnection}{Queued Connection} The slot is invoked + \li \l{Qt::QueuedConnection}{Queued Connection} The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. - \o \l{Qt::BlockingQueuedConnection}{Blocking Queued Connection} + \li \l{Qt::BlockingQueuedConnection}{Blocking Queued Connection} The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns. \note Using this type to connect objects in the same thread will cause deadlock. - \o \l{Qt::UniqueConnection}{Unique Connection} The behavior is the + \li \l{Qt::UniqueConnection}{Unique Connection} The behavior is the same as the Auto Connection, but the connection is made only if it does not duplicate an existing connection. i.e., if the same signal is already connected to the same slot for the same pair @@ -546,33 +546,33 @@ \list - \o QtConcurrent::map() applies a function to every item in a container, + \li QtConcurrent::map() applies a function to every item in a container, modifying the items in-place. - \o QtConcurrent::mapped() is like map(), except that it returns a new + \li QtConcurrent::mapped() is like map(), except that it returns a new container with the modifications. - \o QtConcurrent::mappedReduced() is like mapped(), except that the + \li QtConcurrent::mappedReduced() is like mapped(), except that the modified results are reduced or folded into a single result. - \o QtConcurrent::filter() removes all items from a container based on the + \li QtConcurrent::filter() removes all items from a container based on the result of a filter function. - \o QtConcurrent::filtered() is like filter(), except that it returns a new + \li QtConcurrent::filtered() is like filter(), except that it returns a new container with the filtered results. - \o QtConcurrent::filteredReduced() is like filtered(), except that the + \li QtConcurrent::filteredReduced() is like filtered(), except that the filtered results are reduced or folded into a single result. - \o QtConcurrent::run() runs a function in another thread. + \li QtConcurrent::run() runs a function in another thread. - \o QFuture represents the result of an asynchronous computation. + \li QFuture represents the result of an asynchronous computation. - \o QFutureIterator allows iterating through results available via QFuture. + \li QFutureIterator allows iterating through results available via QFuture. - \o QFutureWatcher allows monitoring a QFuture using signals-and-slots. + \li QFutureWatcher allows monitoring a QFuture using signals-and-slots. - \o QFutureSynchronizer is a convenience class that automatically + \li QFutureSynchronizer is a convenience class that automatically synchronizes several QFutures. \endlist @@ -585,29 +585,29 @@ \table \header - \o Iterator Type - \o Example classes - \o Support status + \li Iterator Type + \li Example classes + \li Support status \row - \o Input Iterator - \o - \o Not Supported + \li Input Iterator + \li + \li Not Supported \row - \o Output Iterator - \o - \o Not Supported + \li Output Iterator + \li + \li Not Supported \row - \o Forward Iterator - \o std::slist - \o Supported + \li Forward Iterator + \li std::slist + \li Supported \row - \o Bidirectional Iterator - \o QLinkedList, std::list - \o Supported + \li Bidirectional Iterator + \li QLinkedList, std::list + \li Supported \row - \o Random Access Iterator - \o QList, QVector, std::vector - \o Supported and Recommended + \li Random Access Iterator + \li QList, QVector, std::vector + \li Supported and Recommended \endtable Random access iterators can be faster in cases where Qt Concurrent is iterating diff --git a/doc/src/examples/addressbook.qdoc b/doc/src/examples/addressbook.qdoc index 02820307e6..51712d49d3 100644 --- a/doc/src/examples/addressbook.qdoc +++ b/doc/src/examples/addressbook.qdoc @@ -107,15 +107,15 @@ dimensions of the model. Whereas, \c rowCount()'s value will vary depending on the number of contacts added to the address book, \c columnCount()'s value is always 2 because we only need space - for the \bold Name and \bold Address columns. + for the \b Name and \b Address columns. \note The \c Q_UNUSED() macro prevents the compiler from generating warnings regarding unused parameters. \snippet itemviews/addressbook/tablemodel.cpp 1 - The \c data() function returns either a \bold Name or - \bold {Address}, based on the contents of the model index + The \c data() function returns either a \b Name or + \b {Address}, based on the contents of the model index supplied. The row number stored in the model index is used to reference an item in the list of pairs. Selection is handled by the QItemSelectionModel, which will be explained with @@ -124,7 +124,7 @@ \snippet itemviews/addressbook/tablemodel.cpp 2 The \c headerData() function displays the table's header, - \bold Name and \bold Address. If you require numbered entries + \b Name and \b Address. If you require numbered entries for your address book, you can use a vertical header which we have hidden in this example (see the \c AddressWidget implementation). @@ -372,8 +372,8 @@ menus and actions necessary to manipulate the address book. \table - \row \o \inlineimage addressbook-filemenu.png - \o \inlineimage addressbook-toolsmenu.png + \row \li \inlineimage addressbook-filemenu.png + \li \inlineimage addressbook-toolsmenu.png \endtable \snippet itemviews/addressbook/mainwindow.h 0 diff --git a/doc/src/examples/affine.qdoc b/doc/src/examples/affine.qdoc index df85576e84..c01031190a 100644 --- a/doc/src/examples/affine.qdoc +++ b/doc/src/examples/affine.qdoc @@ -39,10 +39,10 @@ in the following ways: \list - \o Dragging the red circle in the centre of each drawing moves it to a new position. - \o Dragging the displaced red circle causes the current drawing to be rotated about the + \li Dragging the red circle in the centre of each drawing moves it to a new position. + \li Dragging the displaced red circle causes the current drawing to be rotated about the central circle. Rotation can also be controlled with the \key Rotate slider. - \o Scaling is controlled with the \key Scale slider. - \o Each drawing can be sheared with the \key Shear slider. + \li Scaling is controlled with the \key Scale slider. + \li Each drawing can be sheared with the \key Shear slider. \endlist */ diff --git a/doc/src/examples/arrowpad.qdoc b/doc/src/examples/arrowpad.qdoc index ee35aa59ae..79bf94c510 100644 --- a/doc/src/examples/arrowpad.qdoc +++ b/doc/src/examples/arrowpad.qdoc @@ -142,18 +142,18 @@ Now, enter the following translations: \list - \o \c ArrowPad + \li \c ArrowPad \list - \o \&Up - \&Haut - \o \&Left - \&Gauche - \o \&Right - \&Droite - \o \&Down - \&Bas + \li \&Up - \&Haut + \li \&Left - \&Gauche + \li \&Right - \&Droite + \li \&Down - \&Bas \endlist - \o \c MainWindow + \li \c MainWindow \list - \o E\&xit - \&Quitter - \o Ctrl+Q - Ctrl+Q - \o \&File - \&Fichier + \li E\&xit - \&Quitter + \li Ctrl+Q - Ctrl+Q + \li \&File - \&Fichier \endlist \endlist @@ -164,18 +164,18 @@ Save the file and do the same for Dutch working with \c arrowpad_nl.ts: \list - \o \c ArrowPad + \li \c ArrowPad \list - \o \&Up - \&Omhoog - \o \&Left - \&Links - \o \&Right - \&Rechts - \o \&Down - Omlaa\&g + \li \&Up - \&Omhoog + \li \&Left - \&Links + \li \&Right - \&Rechts + \li \&Down - Omlaa\&g \endlist - \o \c MainWindow + \li \c MainWindow \list - \o E\&xit - \&Afsluiten - \o Ctrl+Q - Ctrl+A - \o File - \&Bestand + \li E\&xit - \&Afsluiten + \li Ctrl+Q - Ctrl+A + \li File - \&Bestand \endlist \endlist diff --git a/doc/src/examples/basicdrawing.qdoc b/doc/src/examples/basicdrawing.qdoc index 3920811e30..501b791bc1 100644 --- a/doc/src/examples/basicdrawing.qdoc +++ b/doc/src/examples/basicdrawing.qdoc @@ -53,9 +53,9 @@ The Basic Drawing example consists of two classes: \list - \o \c RenderArea is a custom widget that renders multiple + \li \c RenderArea is a custom widget that renders multiple copies of the currently active shape. - \o \c Window is the application's main window displaying a + \li \c Window is the application's main window displaying a \c RenderArea widget in addition to several parameter widgets. \endlist @@ -415,19 +415,19 @@ the associated QPainter drawing function: \list - \o QPainter::drawLine(), - \o QPainter::drawPoints(), - \o QPainter::drawPolyline(), - \o QPainter::drawPolygon(), - \o QPainter::drawRect(), - \o QPainter::drawRoundedRect(), - \o QPainter::drawEllipse(), - \o QPainter::drawArc(), - \o QPainter::drawChord(), - \o QPainter::drawPie(), - \o QPainter::drawPath(), - \o QPainter::drawText() or - \o QPainter::drawPixmap() + \li QPainter::drawLine(), + \li QPainter::drawPoints(), + \li QPainter::drawPolyline(), + \li QPainter::drawPolygon(), + \li QPainter::drawRect(), + \li QPainter::drawRoundedRect(), + \li QPainter::drawEllipse(), + \li QPainter::drawArc(), + \li QPainter::drawChord(), + \li QPainter::drawPie(), + \li QPainter::drawPath(), + \li QPainter::drawText() or + \li QPainter::drawPixmap() \endlist Before we started rendering, we saved the current painter state diff --git a/doc/src/examples/basicgraphicslayouts.qdoc b/doc/src/examples/basicgraphicslayouts.qdoc index c1703c3430..b7023cf9ca 100644 --- a/doc/src/examples/basicgraphicslayouts.qdoc +++ b/doc/src/examples/basicgraphicslayouts.qdoc @@ -57,9 +57,9 @@ We repeat the process: \list - \o create a new \c LayoutItem, - \o add the item \c linear, and - \o provide a stretch factor. + \li create a new \c LayoutItem, + \li add the item \c linear, and + \li provide a stretch factor. \endlist \snippet examples/graphicsview/basicgraphicslayouts/window.cpp 1 diff --git a/doc/src/examples/blockingfortuneclient.qdoc b/doc/src/examples/blockingfortuneclient.qdoc index 34add534d4..6c3be78859 100644 --- a/doc/src/examples/blockingfortuneclient.qdoc +++ b/doc/src/examples/blockingfortuneclient.qdoc @@ -38,14 +38,14 @@ \list - \o \e{The asynchronous (non-blocking) approach.} Operations are scheduled + \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled and performed when control returns to Qt's event loop. When the operation is finished, QTcpSocket emits a signal. For example, QTcpSocket::connectToHost() returns immediately, and when the connection has been established, QTcpSocket emits \l{QTcpSocket::connected()}{connected()}. - \o \e{The synchronous (blocking) approach.} In non-GUI and multithreaded + \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded applications, you can call the \c waitFor...() functions (e.g., QTcpSocket::waitForConnected()) to suspend the calling thread until the operation has completed, instead of connecting to signals. diff --git a/doc/src/examples/boxes.qdoc b/doc/src/examples/boxes.qdoc index f2ca92477a..aa34a61bc3 100644 --- a/doc/src/examples/boxes.qdoc +++ b/doc/src/examples/boxes.qdoc @@ -37,11 +37,11 @@ Elements in the demo can be controlled using the mouse in the following ways: \list - \o Dragging the mouse while pressing the left mouse button rotates the + \li Dragging the mouse while pressing the left mouse button rotates the box in the center. - \o Dragging the mouse while pressing the right mouse button rotates the + \li Dragging the mouse while pressing the right mouse button rotates the satellite boxes. - \o Scrolling the mouse wheel zooms in and out of the scene. + \li Scrolling the mouse wheel zooms in and out of the scene. \endlist The options pane can be used to fine-tune various parameters in the demo, diff --git a/doc/src/examples/cachedtable.qdoc b/doc/src/examples/cachedtable.qdoc index d6b0aa5013..c9945a0efb 100644 --- a/doc/src/examples/cachedtable.qdoc +++ b/doc/src/examples/cachedtable.qdoc @@ -66,9 +66,9 @@ in additon to the model and the editor's buttons. \table 100% - \header \o Connecting to a Database + \header \li Connecting to a Database \row - \o + \li Before we can use the \c TableEditor class, we must create a connection to the database containing the table we want to edit: @@ -187,8 +187,8 @@ \table 100% \row - \o - \bold {See also:} + \li + \b {See also:} A complete list of Qt's SQL \l {Database Classes}, and the \l {Model/View Programming} documentation. diff --git a/doc/src/examples/calculator.qdoc b/doc/src/examples/calculator.qdoc index eb3ccedc35..8eddfa8c4e 100644 --- a/doc/src/examples/calculator.qdoc +++ b/doc/src/examples/calculator.qdoc @@ -38,9 +38,9 @@ The example consists of two classes: \list - \o \c Calculator is the calculator widget, with all the + \li \c Calculator is the calculator widget, with all the calculator functionality. - \o \c Button is the widget used for each of the calculator + \li \c Button is the widget used for each of the calculator button. It derives from QToolButton. \endlist @@ -85,18 +85,18 @@ display (a QLineEdit), encode the state of the calculator: \list - \o \c sumInMemory contains the value stored in the calculator's memory + \li \c sumInMemory contains the value stored in the calculator's memory (using \gui{MS}, \gui{M+}, or \gui{MC}). - \o \c sumSoFar stores the value accumulated so far. When the user + \li \c sumSoFar stores the value accumulated so far. When the user clicks \gui{=}, \c sumSoFar is recomputed and shown on the display. \gui{Clear All} resets \c sumSoFar to zero. - \o \c factorSoFar stores a temporary value when doing + \li \c factorSoFar stores a temporary value when doing multiplications and divisions. - \o \c pendingAdditiveOperator stores the last additive operator + \li \c pendingAdditiveOperator stores the last additive operator clicked by the user. - \o \c pendingMultiplicativeOperator stores the last multiplicative operator + \li \c pendingMultiplicativeOperator stores the last multiplicative operator clicked by the user. - \o \c waitingForOperand is \c true when the calculator is + \li \c waitingForOperand is \c true when the calculator is expecting the user to start typing an operand. \endlist @@ -109,16 +109,16 @@ the user enters a mathematical expression. \table - \header \o User Input \o Display \o Sum so Far \o Add. Op. \o Factor so Far \o Mult. Op. \o Waiting for Operand? - \row \o \o 0 \o 0 \o \o \o \o \c true - \row \o \gui{1} \o 1 \o 0 \o \o \o \o \c false - \row \o \gui{1 +} \o 1 \o 1 \o \gui{+} \o \o \o \c true - \row \o \gui{1 + 2} \o 2 \o 1 \o \gui{+} \o \o \o \c false - \row \o \gui{1 + 2 \unicode{247}} \o 2 \o 1 \o \gui{+} \o 2 \o \gui{\unicode{247}} \o \c true - \row \o \gui{1 + 2 \unicode{247} 3} \o 3 \o 1 \o \gui{+} \o 2 \o \gui{\unicode{247}} \o \c false - \row \o \gui{1 + 2 \unicode{247} 3 -} \o 1.66667 \o 1.66667 \o \gui{-} \o \o \o \c true - \row \o \gui{1 + 2 \unicode{247} 3 - 4} \o 4 \o 1.66667 \o \gui{-} \o \o \o \c false - \row \o \gui{1 + 2 \unicode{247} 3 - 4 =} \o -2.33333 \o 0 \o \o \o \o \c true + \header \li User Input \li Display \li Sum so Far \li Add. Op. \li Factor so Far \li Mult. Op. \li Waiting for Operand? + \row \li \li 0 \li 0 \li \li \li \li \c true + \row \li \gui{1} \li 1 \li 0 \li \li \li \li \c false + \row \li \gui{1 +} \li 1 \li 1 \li \gui{+} \li \li \li \c true + \row \li \gui{1 + 2} \li 2 \li 1 \li \gui{+} \li \li \li \c false + \row \li \gui{1 + 2 \unicode{247}} \li 2 \li 1 \li \gui{+} \li 2 \li \gui{\unicode{247}} \li \c true + \row \li \gui{1 + 2 \unicode{247} 3} \li 3 \li 1 \li \gui{+} \li 2 \li \gui{\unicode{247}} \li \c false + \row \li \gui{1 + 2 \unicode{247} 3 -} \li 1.66667 \li 1.66667 \li \gui{-} \li \li \li \c true + \row \li \gui{1 + 2 \unicode{247} 3 - 4} \li 4 \li 1.66667 \li \gui{-} \li \li \li \c false + \row \li \gui{1 + 2 \unicode{247} 3 - 4 =} \li -2.33333 \li 0 \li \li \li \li \c true \endtable Unary operators, such as \gui Sqrt, require no special handling; @@ -356,8 +356,8 @@ base class (QToolButton) but modify it in the following ways: \list - \o We add 20 to the \l{QSize::height()}{height} component of the size hint. - \o We make the \l{QSize::width()}{width} component of the size + \li We add 20 to the \l{QSize::height()}{height} component of the size hint. + \li We make the \l{QSize::width()}{width} component of the size hint at least as much as the \l{QSize::width()}{height}. \endlist diff --git a/doc/src/examples/calendar.qdoc b/doc/src/examples/calendar.qdoc index d06bed7c6f..aea9805669 100644 --- a/doc/src/examples/calendar.qdoc +++ b/doc/src/examples/calendar.qdoc @@ -37,10 +37,10 @@ Specifically, the example demonstrates the following: \list - \o Use of a text editor with a text document - \o Insertion of tables and frames into a document - \o Navigation within a table - \o Insert text in different styles + \li Use of a text editor with a text document + \li Insertion of tables and frames into a document + \li Navigation within a table + \li Insert text in different styles \endlist The rich text editor used to display the document is used within a main window diff --git a/doc/src/examples/calendarwidget.qdoc b/doc/src/examples/calendarwidget.qdoc index 7ef99bfc65..0dd20b1491 100644 --- a/doc/src/examples/calendarwidget.qdoc +++ b/doc/src/examples/calendarwidget.qdoc @@ -51,28 +51,28 @@ below. \table - \header \o Property - \o Description - \row \o \l{QCalendarWidget::}{selectedDate} - \o The currently selected date. - \row \o \l{QCalendarWidget::}{minimumDate} - \o The earliest date that can be selected. - \row \o \l{QCalendarWidget::}{maximumDate} - \o The latest date that can be selected. - \row \o \l{QCalendarWidget::}{firstDayOfWeek} - \o The day that is displayed as the first day of the week + \header \li Property + \li Description + \row \li \l{QCalendarWidget::}{selectedDate} + \li The currently selected date. + \row \li \l{QCalendarWidget::}{minimumDate} + \li The earliest date that can be selected. + \row \li \l{QCalendarWidget::}{maximumDate} + \li The latest date that can be selected. + \row \li \l{QCalendarWidget::}{firstDayOfWeek} + \li The day that is displayed as the first day of the week (usually Sunday or Monday). - \row \o \l{QCalendarWidget::}{gridVisible} - \o Whether the grid should be shown. - \row \o \l{QCalendarWidget::}{selectionMode} - \o Whether the user can select a date or not. - \row \o \l{QCalendarWidget::}{horizontalHeaderFormat} - \o The format of the day names in the horizontal header + \row \li \l{QCalendarWidget::}{gridVisible} + \li Whether the grid should be shown. + \row \li \l{QCalendarWidget::}{selectionMode} + \li Whether the user can select a date or not. + \row \li \l{QCalendarWidget::}{horizontalHeaderFormat} + \li The format of the day names in the horizontal header (e.g., "M", "Mon", or "Monday"). - \row \o \l{QCalendarWidget::}{verticalHeaderFormat} - \o The format of the vertical header. - \row \o \l{QCalendarWidget::}{navigationBarVisible} - \o Whether the navigation bar at the top of the calendar + \row \li \l{QCalendarWidget::}{verticalHeaderFormat} + \li The format of the vertical header. + \row \li \l{QCalendarWidget::}{navigationBarVisible} + \li Whether the navigation bar at the top of the calendar widget is shown. \endtable diff --git a/doc/src/examples/charactermap.qdoc b/doc/src/examples/charactermap.qdoc index 33652118ef..5fbcae1fad 100644 --- a/doc/src/examples/charactermap.qdoc +++ b/doc/src/examples/charactermap.qdoc @@ -43,9 +43,9 @@ that may be unavailable or difficult to locate on their keyboards. The example consists of the following classes: \list -\i \c CharacterWidget displays the available characters in the current +\li \c CharacterWidget displays the available characters in the current font and style. -\i \c MainWindow provides a standard main window that contains font and +\li \c MainWindow provides a standard main window that contains font and style information, a view onto the characters, a line edit, and a push button for submitting text to the clipboard. \endlist diff --git a/doc/src/examples/chart.qdoc b/doc/src/examples/chart.qdoc index 565b1c6c7d..947eddf1c9 100644 --- a/doc/src/examples/chart.qdoc +++ b/doc/src/examples/chart.qdoc @@ -37,7 +37,7 @@ relying on the flexibility of the model/view architecture to handle custom editing and selection features. - \bold{Note that you only need to create a new view class if your data requires a + \b{Note that you only need to create a new view class if your data requires a specialized representation.} You should first consider using a standard QListView, QTableView, or QTreeView with a custom QItemDelegate subclass if you need to represent data in a special way. @@ -61,10 +61,10 @@ We interpret the data in the following way: \list - \o Column 0 contains data in two different roles: + \li Column 0 contains data in two different roles: The \l{Qt::ItemDataRole}{DisplayRole} contains a label, and the \l{Qt::ItemDataRole}{DecorationRole} contains the color of the pie slice. - \o Column 1 contains a quantity which we will convert to the angular extent of + \li Column 1 contains a quantity which we will convert to the angular extent of the slice. \endlist diff --git a/doc/src/examples/classwizard.qdoc b/doc/src/examples/classwizard.qdoc index 0fad22e56a..8f84193f2e 100644 --- a/doc/src/examples/classwizard.qdoc +++ b/doc/src/examples/classwizard.qdoc @@ -44,10 +44,10 @@ The Class Wizard example consists of the following classes: \list - \o \c ClassWizard inherits QWizard and provides a + \li \c ClassWizard inherits QWizard and provides a three-step wizard that generates the skeleton of a C++ class based on the user's input. - \o \c IntroPage, \c ClassInfoPage, \c CodeStylePage, \c + \li \c IntroPage, \c ClassInfoPage, \c CodeStylePage, \c OutputFilesPage, and \c ConclusionPage are QWizardPage subclasses that implement the wizard pages. \endlist @@ -61,17 +61,17 @@ five pages: \list - \o The first page is an introduction page, telling the user what + \li The first page is an introduction page, telling the user what the wizard is going to do. - \o The second page asks for a class name and a base class, and + \li The second page asks for a class name and a base class, and allows the user to specify whether the class should have a \c Q_OBJECT macro and what constructors it should provide. - \o The third page allows the user to set some options related to the code + \li The third page allows the user to set some options related to the code style, such as the macro used to protect the header file from multiple inclusion (e.g., \c MYDIALOG_H). - \o The fourth page allows the user to specify the names of the + \li The fourth page allows the user to specify the names of the output files. - \o The fifth page is a conclusion page. + \li The fifth page is a conclusion page. \endlist Although the program is just an example, if you press \gui Finish diff --git a/doc/src/examples/coloreditorfactory.qdoc b/doc/src/examples/coloreditorfactory.qdoc index 741db7e387..1806446fb7 100644 --- a/doc/src/examples/coloreditorfactory.qdoc +++ b/doc/src/examples/coloreditorfactory.qdoc @@ -134,16 +134,16 @@ Possible suggestions are: \list - \o If the editor widget has no user property defined, the delegate + \li If the editor widget has no user property defined, the delegate asks the factory for the property name, which it in turn asks the item editor creator for. In this case, you can use the QItemEditorCreator class, which takes the property name to use for editing as a constructor argument. - \o If the editor requires other constructors or other + \li If the editor requires other constructors or other initialization than provided by QItemEditorCreatorBase, you must reimplement QItemEditorCreatorBase::createWidget(). - \o You could also subclass QItemEditorFactory if you only want + \li You could also subclass QItemEditorFactory if you only want to provide editors for certain kinds of data or use another method of creating the editors than using creator bases. \endlist diff --git a/doc/src/examples/completer.qdoc b/doc/src/examples/completer.qdoc index 767efe8ef1..df832de4d6 100644 --- a/doc/src/examples/completer.qdoc +++ b/doc/src/examples/completer.qdoc @@ -77,8 +77,8 @@ The screenshots below illustrate this difference: \table - \row \o \inlineimage completer-example-qdirmodel.png - \o \inlineimage completer-example-dirmodel.png + \row \li \inlineimage completer-example-qdirmodel.png + \li \inlineimage completer-example-dirmodel.png \endtable The Qt::EditRole, which QCompleter uses to look for matches, is left diff --git a/doc/src/examples/composition.qdoc b/doc/src/examples/composition.qdoc index 1da41dbfef..6aca01d255 100644 --- a/doc/src/examples/composition.qdoc +++ b/doc/src/examples/composition.qdoc @@ -33,10 +33,10 @@ \image composition-demo.png - The two most common forms of composition are \bold{Source} and \bold{SourceOver}. - \bold{Source} is used to draw opaque objects onto a paint device. In this mode, + The two most common forms of composition are \b{Source} and \b{SourceOver}. + \b{Source} is used to draw opaque objects onto a paint device. In this mode, each pixel in the source replaces the corresponding pixel in the destination. - In \bold{SourceOver} composition mode, the source object is transparent and is + In \b{SourceOver} composition mode, the source object is transparent and is drawn on top of the destination. In addition to these standard modes, Qt defines the complete set of composition modes diff --git a/doc/src/examples/concentriccircles.qdoc b/doc/src/examples/concentriccircles.qdoc index 73b4937049..22b0be8fb8 100644 --- a/doc/src/examples/concentriccircles.qdoc +++ b/doc/src/examples/concentriccircles.qdoc @@ -59,9 +59,9 @@ The example consists of two classes: \list - \o \c CircleWidget is a custom widget which renders several animated + \li \c CircleWidget is a custom widget which renders several animated concentric circles. - \o \c Window is the application's main window displaying four \c + \li \c Window is the application's main window displaying four \c {CircleWidget}s drawn using different combinations of precision and aliasing. \endlist diff --git a/doc/src/examples/cube.qdoc b/doc/src/examples/cube.qdoc index 3c41856254..ec40be0f45 100644 --- a/doc/src/examples/cube.qdoc +++ b/doc/src/examples/cube.qdoc @@ -61,9 +61,9 @@ The example consist of two classes: \list - \o \c MainWidget extends QGLWidget and contains OpenGL ES 2.0 + \li \c MainWidget extends QGLWidget and contains OpenGL ES 2.0 initialization and drawing and mouse and timer event handling - \o \c GeometryEngine handles polygon geometries. Transfers polygon geometry + \li \c GeometryEngine handles polygon geometries. Transfers polygon geometry to vertex buffer objects and draws geometries from vertex buffer objects. \endlist diff --git a/doc/src/examples/customsortfiltermodel.qdoc b/doc/src/examples/customsortfiltermodel.qdoc index ac9fbb93a3..61230a7b9a 100644 --- a/doc/src/examples/customsortfiltermodel.qdoc +++ b/doc/src/examples/customsortfiltermodel.qdoc @@ -48,10 +48,10 @@ \list - \o The \c MySortFilterProxyModel class provides a custom proxy + \li The \c MySortFilterProxyModel class provides a custom proxy model. - \o The \c Window class provides the main application window, + \li The \c Window class provides the main application window, using the custom proxy model to sort and filter a standard item model. diff --git a/doc/src/examples/dbscreen.qdoc b/doc/src/examples/dbscreen.qdoc index 7d9cea5519..bfecb9a3cb 100644 --- a/doc/src/examples/dbscreen.qdoc +++ b/doc/src/examples/dbscreen.qdoc @@ -36,13 +36,13 @@ to writing and implementing this graphics driver: \list 1 - \o \l {Step 1: Creating a Custom Graphics Driver} + \li \l {Step 1: Creating a Custom Graphics Driver} {Creating a Custom Graphics Driver} - \o \l {Step 2: Implementing the Back Buffer} + \li \l {Step 2: Implementing the Back Buffer} {Implementing the Back Buffer} - \o \l {Step 3: Creating the Driver Plugin} + \li \l {Step 3: Creating the Driver Plugin} {Creating the Driver Plugin} \endlist @@ -71,11 +71,11 @@ functions belonging to QScreen: \list - \o \l{QScreen::initDevice()}{initDevice()}, - \o \l{QScreen::shutdownDevice()}{shutdownDevice()}, - \o \l{QScreen::blit()}{blit()}, - \o \l{QScreen::solidFill()}{solidFill()}, and - \o \l{QScreen::exposeRegion()}{exposeRegion()}. + \li \l{QScreen::initDevice()}{initDevice()}, + \li \l{QScreen::shutdownDevice()}{shutdownDevice()}, + \li \l{QScreen::blit()}{blit()}, + \li \l{QScreen::solidFill()}{solidFill()}, and + \li \l{QScreen::exposeRegion()}{exposeRegion()}. \endlist \snippet examples/qws/dbscreen/dbscreen.h 0 @@ -89,10 +89,10 @@ The graphics driver must carry out three main functions: \list 1 - \o Allocate the back buffer on startup and deallocate it on shutdown. - \o Draw to the back buffer instead of directly to the screen + \li Allocate the back buffer on startup and deallocate it on shutdown. + \li Draw to the back buffer instead of directly to the screen (which is what QLinuxFbScreen does). - \o Copy the back buffer to the screen whenever a screen update is + \li Copy the back buffer to the screen whenever a screen update is done. \endlist @@ -165,9 +165,9 @@ There are only two functions to reimplement: \list - \o \l{QScreenDriverPlugin::create()}{create()} - creates a driver + \li \l{QScreenDriverPlugin::create()}{create()} - creates a driver matching the given key - \o \l{QScreenDriverPlugin::create()}{keys()} - returns a list of + \li \l{QScreenDriverPlugin::create()}{keys()} - returns a list of valid keys representing the drivers supported by the plugin \endlist diff --git a/doc/src/examples/diagramscene.qdoc b/doc/src/examples/diagramscene.qdoc index 9f2a8f8b76..ac9ca2f294 100644 --- a/doc/src/examples/diagramscene.qdoc +++ b/doc/src/examples/diagramscene.qdoc @@ -55,28 +55,28 @@ In particular we show how to: \list - \o Create custom graphics items. - \o Handle mouse events and movement of items. - \o Implement a graphics scene that can manage our custom items. - \o Custom painting of items. - \o Create a movable and editable text item. + \li Create custom graphics items. + \li Handle mouse events and movement of items. + \li Implement a graphics scene that can manage our custom items. + \li Custom painting of items. + \li Create a movable and editable text item. \endlist The example consists of the following classes: \list - \o \c MainWindow creates the widgets and display + \li \c MainWindow creates the widgets and display them in a QMainWindow. It also manages the interaction between the widgets and the graphics scene, view and items. - \o \c DiagramItem inherits QGraphicsPolygonItem and + \li \c DiagramItem inherits QGraphicsPolygonItem and represents a flowchart shape. - \o \c TextDiagramItem inherits QGraphicsTextItem and + \li \c TextDiagramItem inherits QGraphicsTextItem and represents text items in the diagram. The class adds support for moving the item with the mouse, which is not supported by QGraphicsTextItem. - \o \c Arrow inherits QGraphicsLineItem and is an arrow + \li \c Arrow inherits QGraphicsLineItem and is an arrow that connect two DiagramItems. - \o \c DiagramScene inherits QGraphicsDiagramScene and + \li \c DiagramScene inherits QGraphicsDiagramScene and provides support for \c DiagramItem, \c Arrow and \c DiagramTextItem (In addition to the support already handled by QGraphicsScene). diff --git a/doc/src/examples/drilldown.qdoc b/doc/src/examples/drilldown.qdoc index 1e7b8c01d6..7f195d5261 100644 --- a/doc/src/examples/drilldown.qdoc +++ b/doc/src/examples/drilldown.qdoc @@ -45,13 +45,13 @@ The example consists of three classes: \list - \o \c ImageItem is a custom graphics item class used to + \li \c ImageItem is a custom graphics item class used to display the office images. - \o \c View is the main application widget allowing the user to + \li \c View is the main application widget allowing the user to browse through the various locations. - \o \c InformationWindow displays the requested information, + \li \c InformationWindow displays the requested information, allowing the users to alter it and submit their changes to the database. \endlist diff --git a/doc/src/examples/dropsite.qdoc b/doc/src/examples/dropsite.qdoc index 024d191b74..77b40986aa 100644 --- a/doc/src/examples/dropsite.qdoc +++ b/doc/src/examples/dropsite.qdoc @@ -53,10 +53,10 @@ reimplementations of four \l{QWidget} event handlers: \list 1 - \o \l{QWidget::dragEnterEvent()}{dragEnterEvent()} - \o \l{QWidget::dragMoveEvent()}{dragMoveEvent()} - \o \l{QWidget::dragLeaveEvent()}{dragLeaveEvent()} - \o \l{QWidget::dropEvent()}{dropEvent()} + \li \l{QWidget::dragEnterEvent()}{dragEnterEvent()} + \li \l{QWidget::dragMoveEvent()}{dragMoveEvent()} + \li \l{QWidget::dragLeaveEvent()}{dragLeaveEvent()} + \li \l{QWidget::dropEvent()}{dropEvent()} \endlist These event handlers are further explained in the implementation of the @@ -108,17 +108,17 @@ \snippet draganddrop/dropsite/droparea.cpp dropEvent() function part2 \list - \o If \c mimeData contains an image, we display it in \c DropArea with + \li If \c mimeData contains an image, we display it in \c DropArea with \l{QLabel::setPixmap()}{setPixmap()}. - \o If \c mimeData contains HTML, we display it with + \li If \c mimeData contains HTML, we display it with \l{QLabel::setText()}{setText()} and set \c{DropArea}'s text format as Qt::RichText. - \o If \c mimeData contains plain text, we display it with + \li If \c mimeData contains plain text, we display it with \l{QLabel::setText()}{setText()} and set \c{DropArea}'s text format as Qt::PlainText. In the event that \c mimeData contains URLs, we iterate through the list of URLs to display them on individual lines. - \o If \c mimeData contains other types of objects, we set + \li If \c mimeData contains other types of objects, we set \c{DropArea}'s text, with \l{QLabel::setText()}{setText()} to "Cannot display data" to inform the user. \endlist diff --git a/doc/src/examples/editabletreemodel.qdoc b/doc/src/examples/editabletreemodel.qdoc index 306295842e..958080ad58 100644 --- a/doc/src/examples/editabletreemodel.qdoc +++ b/doc/src/examples/editabletreemodel.qdoc @@ -82,8 +82,8 @@ \target Relations-between-internal-items \table - \row \o \inlineimage itemviews-editabletreemodel-items.png - \o \bold{Relations between internal items} + \row \li \inlineimage itemviews-editabletreemodel-items.png + \li \b{Relations between internal items} When designing a data structure for use with a custom model, it is useful to expose each item's parent via a function like @@ -99,10 +99,10 @@ \l{TreeItem::parent}{parent()} and \l{TreeItem::child}{child()} functions. - In the example shown, two top-level items, \bold{A} and - \bold{B}, can be obtained from the root item by calling its child() + In the example shown, two top-level items, \b{A} and + \b{B}, can be obtained from the root item by calling its child() function, and each of these items return the root node from their - parent() functions, though this is only shown for item \bold{A}. + parent() functions, though this is only shown for item \b{A}. \endtable Each \c TreeItem stores data for each column in the row it represents @@ -126,23 +126,23 @@ horizontal header titles. \table - \row \o \inlineimage itemviews-editabletreemodel-model.png - \o \bold{Accessing data via the model} + \row \li \inlineimage itemviews-editabletreemodel-model.png + \li \b{Accessing data via the model} In the case shown in the diagram, the piece of information represented - by \bold{a} can be obtained using the standard model/view API: + by \b{a} can be obtained using the standard model/view API: \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.cpp 0 Since each items holds pieces of data for each column in a given row, there can be many model indexes that map to the same \c TreeItem object. - For example, the information represented by \bold{b} can be obtained + For example, the information represented by \b{b} can be obtained using the following code: \snippet doc/src/snippets/code/doc_src_examples_editabletreemodel.cpp 1 The same underlying \c TreeItem would be accessed to obtain information - for the other model indexes in the same row as \bold{b}. + for the other model indexes in the same row as \b{b}. \endtable In the model class, \c TreeModel, we relate \c TreeItem objects to @@ -166,20 +166,20 @@ that the model does not attempt to access items that have been deleted. \table - \row \o \bold{Storing information in the underlying data structure} + \row \li \b{Storing information in the underlying data structure} Several pieces of data are stored as QVariant objects in the \c itemData member of each \c TreeItem instance The diagram shows how pieces of information, - represented by the labels \bold{a}, \bold{b} and \bold{c} in the - previous two diagrams, are stored in items \bold{A}, \bold{B} and - \bold{C} in the underlying data structure. Note that pieces of + represented by the labels \b{a}, \b{b} and \b{c} in the + previous two diagrams, are stored in items \b{A}, \b{B} and + \b{C} in the underlying data structure. Note that pieces of information from the same row in the model are all obtained from the same item. Each element in a list corresponds to a piece of information exposed by each column in a given row in the model. - \o \inlineimage itemviews-editabletreemodel-values.png + \li \inlineimage itemviews-editabletreemodel-values.png \endtable Since the \c TreeModel implementation has been designed for use with @@ -202,8 +202,8 @@ \target Relating-items-using-model-indexes \table \row - \o \inlineimage itemviews-editabletreemodel-indexes.png - \o \bold{Relating items using model indexes} + \li \inlineimage itemviews-editabletreemodel-indexes.png + \li \b{Relating items using model indexes} As with the \l{itemviews/simpletreemodel}{Simple Tree Model} example, the \c TreeModel needs to be able to take a model index, find the @@ -215,13 +215,13 @@ an item supplied by the caller, using the items shown in a \l{Relations-between-internal-items}{previous diagram}. - A pointer to item \bold{C} is obtained from the corresponding model index + A pointer to item \b{C} is obtained from the corresponding model index using the \l{QModelIndex::internalPointer()} function. The pointer was stored internally in the index when it was created. Since the child contains a pointer to its parent, we use its \l{TreeItem::parent}{parent()} - function to obtain a pointer to item \bold{B}. The parent model index is + function to obtain a pointer to item \b{B}. The parent model index is created using the QAbstractItemModel::createIndex() function, passing - the pointer to item \bold{B} as the internal pointer. + the pointer to item \b{B} as the internal pointer. \endtable \section1 TreeItem Class Definition diff --git a/doc/src/examples/elasticnodes.qdoc b/doc/src/examples/elasticnodes.qdoc index 51a0a6048a..bd25008f60 100644 --- a/doc/src/examples/elasticnodes.qdoc +++ b/doc/src/examples/elasticnodes.qdoc @@ -54,9 +54,9 @@ The \c Node class serves three purposes: \list - \o Painting a yellow gradient "ball" in two states: sunken and raised. - \o Managing connections to other nodes. - \o Calculating forces pulling and pushing the nodes in the grid. + \li Painting a yellow gradient "ball" in two states: sunken and raised. + \li Managing connections to other nodes. + \li Calculating forces pulling and pushing the nodes in the grid. \endlist Let's start by looking at the \c Node class declaration. diff --git a/doc/src/examples/fortuneclient.qdoc b/doc/src/examples/fortuneclient.qdoc index f2c6fa02d9..d997fc077e 100644 --- a/doc/src/examples/fortuneclient.qdoc +++ b/doc/src/examples/fortuneclient.qdoc @@ -47,14 +47,14 @@ \list - \o \e{The asynchronous (non-blocking) approach.} Operations are scheduled + \li \e{The asynchronous (non-blocking) approach.} Operations are scheduled and performed when control returns to Qt's event loop. When the operation is finished, QTcpSocket emits a signal. For example, QTcpSocket::connectToHost() returns immediately, and when the connection has been established, QTcpSocket emits \l{QTcpSocket::connected()}{connected()}. - \o \e{The synchronous (blocking) approach.} In non-GUI and multithreaded + \li \e{The synchronous (blocking) approach.} In non-GUI and multithreaded applications, you can call the \c waitFor...() functions (e.g., QTcpSocket::waitForConnected()) to suspend the calling thread until the operation has completed, instead of connecting to signals. @@ -107,11 +107,11 @@ one of two things can happen: \list - \o \e{The connection is established.} In this case, the server will send us a + \li \e{The connection is established.} In this case, the server will send us a fortune. QTcpSocket will emit \l{QTcpSocket::readyRead()}{readyRead()} every time it receives a block of data. - \o \e{An error occurs.} We need to inform the user if the connection + \li \e{An error occurs.} We need to inform the user if the connection failed or was broken. In this case, QTcpSocket will emit \l{QTcpSocket::error()}{error()}, and \c Client::displayError() will be called. diff --git a/doc/src/examples/fridgemagnets.qdoc b/doc/src/examples/fridgemagnets.qdoc index b2bd440707..7b7218bba2 100644 --- a/doc/src/examples/fridgemagnets.qdoc +++ b/doc/src/examples/fridgemagnets.qdoc @@ -39,9 +39,9 @@ the words on the magnets. The example consists of two classes: \list - \o \c DragLabel is a custom widget representing one + \li \c DragLabel is a custom widget representing one single fridge magnet. - \o \c DragWidget provides the main application window. + \li \c DragWidget provides the main application window. \endlist We will first take a look at the \c DragLabel class, then we will diff --git a/doc/src/examples/gradients.qdoc b/doc/src/examples/gradients.qdoc index 75876fdf2c..75f78b56ea 100644 --- a/doc/src/examples/gradients.qdoc +++ b/doc/src/examples/gradients.qdoc @@ -37,10 +37,10 @@ There are three types of gradients: \list - \o \bold{Linear} gradients interpolate colors between start and end points. - \o \bold{Radial} gradients interpolate colors between a focal point and the + \li \b{Linear} gradients interpolate colors between start and end points. + \li \b{Radial} gradients interpolate colors between a focal point and the points on a circle surrounding it. - \o \bold{Conical} gradients interpolate colors around a center point. + \li \b{Conical} gradients interpolate colors around a center point. \endlist The panel on the right contains a color table editor that defines diff --git a/doc/src/examples/hellogl.qdoc b/doc/src/examples/hellogl.qdoc index a0b6fc6c06..f6f8591ad0 100644 --- a/doc/src/examples/hellogl.qdoc +++ b/doc/src/examples/hellogl.qdoc @@ -285,12 +285,12 @@ by reimplementing the following functions: \list - \o QGLWidget::initializeGL() sets up resources needed by the OpenGL implementation + \li QGLWidget::initializeGL() sets up resources needed by the OpenGL implementation to render the scene. - \o QGLWidget::resizeGL() resizes the viewport so that the rendered scene fits onto + \li QGLWidget::resizeGL() resizes the viewport so that the rendered scene fits onto the widget, and sets up a projection matrix to map 3D coordinates to 2D viewport coordinates. - \o QGLWidget::paintGL() performs painting operations using OpenGL calls. + \li QGLWidget::paintGL() performs painting operations using OpenGL calls. \endlist Since QGLWidget is a subclass of QWidget, it can also be used diff --git a/doc/src/examples/icons.qdoc b/doc/src/examples/icons.qdoc index be7b0dd46c..9e7dda7c89 100644 --- a/doc/src/examples/icons.qdoc +++ b/doc/src/examples/icons.qdoc @@ -47,24 +47,24 @@ of the icon. Qt currently defines four modes: \table - \header \o Mode \o Description + \header \li Mode \li Description \row - \o QIcon::Normal - \o Display the pixmap when the user is not interacting with the + \li QIcon::Normal + \li Display the pixmap when the user is not interacting with the icon, but the functionality represented by the icon is available. \row - \o QIcon::Active - \o Display the pixmap when the functionality represented by the + \li QIcon::Active + \li Display the pixmap when the functionality represented by the icon is available and the user is interacting with the icon, for example, moving the mouse over it or clicking it. \row - \o QIcon::Disabled - \o Display the pixmap when the functionality represented by + \li QIcon::Disabled + \li Display the pixmap when the functionality represented by the icon is not available. \row - \o QIcon::Selected - \o Display the pixmap when the icon is selected. + \li QIcon::Selected + \li Display the pixmap when the icon is selected. \endtable QIcon's states are QIcon::On and QIcon::Off, which will display @@ -148,16 +148,16 @@ search algorithm described in the table below: \table 100% - \header \o{2,1} Requested Pixmap \o {8,1} Preferred Alternatives (mode/state) - \header \o Mode \o State \o 1 \o 2 \o 3 \o 4 \o 5 \o 6 \o 7 \o 8 - \row \o{1,2} Normal \o Off \o \bold N0 \o A0 \o N1 \o A1 \o D0 \o S0 \o D1 \o S1 - \row \o On \o N1 \o \bold A1 \o N0 \o A0 \o D1 \o S1 \o D0 \o S0 - \row \o{1,2} Active \o Off \o A0 \o \bold N0 \o A1 \o N1 \o D0 \o S0 \o D1 \o S1 - \row \o On \o \bold A1 \o N1 \o A0 \o N0 \o D1 \o S1 \o D0 \o S0 - \row \o{1,2} Disabled \o Off \o D0 \o \bold {N0'} \o A0' \o D1 \o N1' \o A1' \o S0' \o S1' - \row \o On \o D1 \o N1' \o \bold {A1'} \o D0 \o N0' \o A0' \o S1' \o S0' - \row \o{1,2} Selected \o Off \o S0 \o \bold {N0''} \o A0'' \o S1 \o N1'' \o A1'' \o D0'' \o D1'' - \row \o On \o S1 \o N1'' \o \bold {A1''} \o S0 \o N0'' \o A0'' \o D1'' \o D0'' + \header \li{2,1} Requested Pixmap \li {8,1} Preferred Alternatives (mode/state) + \header \li Mode \li State \li 1 \li 2 \li 3 \li 4 \li 5 \li 6 \li 7 \li 8 + \row \li{1,2} Normal \li Off \li \b N0 \li A0 \li N1 \li A1 \li D0 \li S0 \li D1 \li S1 + \row \li On \li N1 \li \b A1 \li N0 \li A0 \li D1 \li S1 \li D0 \li S0 + \row \li{1,2} Active \li Off \li A0 \li \b N0 \li A1 \li N1 \li D0 \li S0 \li D1 \li S1 + \row \li On \li \b A1 \li N1 \li A0 \li N0 \li D1 \li S1 \li D0 \li S0 + \row \li{1,2} Disabled \li Off \li D0 \li \b {N0'} \li A0' \li D1 \li N1' \li A1' \li S0' \li S1' + \row \li On \li D1 \li N1' \li \b {A1'} \li D0 \li N0' \li A0' \li S1' \li S0' + \row \li{1,2} Selected \li Off \li S0 \li \b {N0''} \li A0'' \li S1 \li N1'' \li A1'' \li D0'' \li D1'' + \row \li On \li S1 \li N1'' \li \b {A1''} \li S0 \li N0'' \li A0'' \li D1'' \li D0'' \endtable In the table, "0" and "1" stand for Off" and "On", respectively. @@ -176,8 +176,8 @@ \table \row - \o \inlineimage icons_monkey.png Screenshot of the Monkey Files - \o \inlineimage icons_monkey_mess.png Screenshot of the Monkey Files + \li \inlineimage icons_monkey.png Screenshot of the Monkey Files + \li \inlineimage icons_monkey_mess.png Screenshot of the Monkey Files \endtable For any given mode/state combination, it is possible to specify @@ -193,25 +193,25 @@ \table \row - \o - \o \inlineimage icons_qt_extended_8x8.png Qt Extended icon at 8 x 8 - \o \inlineimage icons_qt_extended_16x16.png Qt Extended icon at 16 x 16 - \o \inlineimage icons_qt_extended_17x17.png Qt Extended icon at 17 x 17 + \li + \li \inlineimage icons_qt_extended_8x8.png Qt Extended icon at 8 x 8 + \li \inlineimage icons_qt_extended_16x16.png Qt Extended icon at 16 x 16 + \li \inlineimage icons_qt_extended_17x17.png Qt Extended icon at 17 x 17 \row - \o - \o 8 x 8 - \o \bold {16 x 16} - \o 17 x 17 + \li + \li 8 x 8 + \li \b {16 x 16} + \li 17 x 17 \row - \o \inlineimage icons_qt_extended_32x32.png Qt Extended icon at 32 x 32 - \o \inlineimage icons_qt_extended_33x33.png Qt Extended icon at 33 x 33 - \o \inlineimage icons_qt_extended_48x48.png Qt Extended icon at 48 x 48 - \o \inlineimage icons_qt_extended_64x64.png Qt Extended icon at 64 x 64 + \li \inlineimage icons_qt_extended_32x32.png Qt Extended icon at 32 x 32 + \li \inlineimage icons_qt_extended_33x33.png Qt Extended icon at 33 x 33 + \li \inlineimage icons_qt_extended_48x48.png Qt Extended icon at 48 x 48 + \li \inlineimage icons_qt_extended_64x64.png Qt Extended icon at 64 x 64 \row - \o \bold {32 x 32} - \o 33 x 33 - \o \bold {48 x 48} - \o 64 x 64 + \li \b {32 x 32} + \li 33 x 33 + \li \b {48 x 48} + \li 64 x 64 \endtable For sizes up to 16 x 16, QIcon uses \c qt_extended_16x16.png and @@ -224,13 +224,13 @@ The Icons example consists of four classes: \list - \o \c MainWindow inherits QMainWindow and is the main application + \li \c MainWindow inherits QMainWindow and is the main application window. - \o \c IconPreviewArea is a custom widget that displays all + \li \c IconPreviewArea is a custom widget that displays all combinations of states and modes for a given icon. - \o \c IconSizeSpinBox is a subclass of QSpinBox that lets the + \li \c IconSizeSpinBox is a subclass of QSpinBox that lets the user enter icon sizes (e.g., "48 x 48"). - \o \c ImageDelegate is a subclass of QItemDelegate that provides + \li \c ImageDelegate is a subclass of QItemDelegate that provides comboboxes for letting the user set the mode and state associated with an image. \endlist @@ -332,13 +332,13 @@ constructor, and declare several private slots: \list - \o The \c about() slot simply provides information about the example. - \o The \c changeStyle() slot changes the application's GUI style and + \li The \c about() slot simply provides information about the example. + \li The \c changeStyle() slot changes the application's GUI style and adjust the style dependent size options. - \o The \c changeSize() slot changes the size of the preview area's icon. - \o The \c changeIcon() slot updates the set of pixmaps available to the + \li The \c changeSize() slot changes the size of the preview area's icon. + \li The \c changeIcon() slot updates the set of pixmaps available to the icon displayed in the preview area. - \o The \c addImage() slot allows the user to load a new image into the + \li The \c addImage() slot allows the user to load a new image into the application. \endlist diff --git a/doc/src/examples/imagecomposition.qdoc b/doc/src/examples/imagecomposition.qdoc index edefcface4..d7700858a0 100644 --- a/doc/src/examples/imagecomposition.qdoc +++ b/doc/src/examples/imagecomposition.qdoc @@ -86,11 +86,11 @@ We connect the following signals to their corresponding slots: \list - \o \c{sourceButton}'s \l{QPushButton::clicked()}{clicked()} signal is + \li \c{sourceButton}'s \l{QPushButton::clicked()}{clicked()} signal is connected to \c chooseSource(), - \o \c{operatorComboBox}'s \l{QComboBox::activated()}{activated()} + \li \c{operatorComboBox}'s \l{QComboBox::activated()}{activated()} signal is connected to \c recalculateResult(), and - \o \c{destinationButton}'s \l{QToolButton::clicked()}{clicked()} signal + \li \c{destinationButton}'s \l{QToolButton::clicked()}{clicked()} signal is connected to \c chooseDestination(). \endlist diff --git a/doc/src/examples/imageviewer.qdoc b/doc/src/examples/imageviewer.qdoc index 18cdccb5ed..638c0c3fb4 100644 --- a/doc/src/examples/imageviewer.qdoc +++ b/doc/src/examples/imageviewer.qdoc @@ -49,18 +49,18 @@ to: \list - \o \gui{Open...} - Open an image file - \o \gui{Print...} - Print an image - \o \gui{Exit} - Exit the application + \li \gui{Open...} - Open an image file + \li \gui{Print...} - Print an image + \li \gui{Exit} - Exit the application \endlist Once an image is loaded, the \gui View menu allows the users to: \list - \o \gui{Zoom In} - Scale the image up by 25% - \o \gui{Zoom Out} - Scale the image down by 25% - \o \gui{Normal Size} - Show the image at its original size - \o \gui{Fit to Window} - Stretch the image to occupy the entire window + \li \gui{Zoom In} - Scale the image up by 25% + \li \gui{Zoom Out} - Scale the image down by 25% + \li \gui{Normal Size} - Show the image at its original size + \li \gui{Fit to Window} - Stretch the image to occupy the entire window \endlist In addition the \gui Help menu provides the users with information @@ -202,9 +202,9 @@ \table \row - \o \inlineimage imageviewer-original_size.png - \o \inlineimage imageviewer-zoom_in_1.png - \o \inlineimage imageviewer-zoom_in_2.png + \li \inlineimage imageviewer-original_size.png + \li \inlineimage imageviewer-zoom_in_1.png + \li \inlineimage imageviewer-zoom_in_2.png \endtable \snippet examples/widgets/imageviewer/imageviewer.cpp 11 @@ -246,9 +246,9 @@ \table \row - \o \inlineimage imageviewer-original_size.png - \o \inlineimage imageviewer-fit_to_window_1.png - \o \inlineimage imageviewer-fit_to_window_2.png + \li \inlineimage imageviewer-original_size.png + \li \inlineimage imageviewer-fit_to_window_1.png + \li \inlineimage imageviewer-fit_to_window_2.png \endtable If the slot is called to turn off the option, the diff --git a/doc/src/examples/licensewizard.qdoc b/doc/src/examples/licensewizard.qdoc index 92e51dec3b..3a325100a7 100644 --- a/doc/src/examples/licensewizard.qdoc +++ b/doc/src/examples/licensewizard.qdoc @@ -50,10 +50,10 @@ The example consists of the following classes: \list - \o \c LicenseWizard inherits QWizard and implements a non-linear + \li \c LicenseWizard inherits QWizard and implements a non-linear five-page wizard that leads the user through the process of choosing a license agreement. - \o \c IntroPage, \c EvaluatePage, \c RegisterPage, \c + \li \c IntroPage, \c EvaluatePage, \c RegisterPage, \c DetailsPage, and \c ConclusionPage are QWizardPage subclasses that implement the wizard pages. \endlist @@ -71,12 +71,12 @@ The enum defines the IDs associated with the various pages: \table - \header \o Class name \o Enum value \o Page ID - \row \o \c IntroPage \o \c Page_Intro \o 0 - \row \o \c EvaluatePage \o \c Page_Evaluate \o 1 - \row \o \c RegisterPage \o \c Page_Register \o 2 - \row \o \c DetailsPage \o \c Page_Details \o 3 - \row \o \c ConclusionPage \o \c Page_Conclusion \o 4 + \header \li Class name \li Enum value \li Page ID + \row \li \c IntroPage \li \c Page_Intro \li 0 + \row \li \c EvaluatePage \li \c Page_Evaluate \li 1 + \row \li \c RegisterPage \li \c Page_Register \li 2 + \row \li \c DetailsPage \li \c Page_Details \li 3 + \row \li \c ConclusionPage \li \c Page_Conclusion \li 4 \endtable For this example, the IDs are arbitrary. The only constraints are @@ -206,11 +206,11 @@ QWidget::setVisible(): \list - \o If the page is shown, we set the \l{QWizard::}{CustomButton1} button's + \li If the page is shown, we set the \l{QWizard::}{CustomButton1} button's text to \gui{\underline{P}rint}, we enable the \l{QWizard::}{HaveCustomButton1} option, and we connect the QWizard's \l{QWizard::}{customButtonClicked()} signal to our \c printButtonClicked() slot. - \o If the page is hidden, we disable the \l{QWizard::}{HaveCustomButton1} + \li If the page is hidden, we disable the \l{QWizard::}{HaveCustomButton1} option and disconnect the \c printButtonClicked() slot. \endlist diff --git a/doc/src/examples/maemovibration.qdoc b/doc/src/examples/maemovibration.qdoc index 855793cf75..78bb7f5334 100644 --- a/doc/src/examples/maemovibration.qdoc +++ b/doc/src/examples/maemovibration.qdoc @@ -47,11 +47,11 @@ The code makes use of two classes: \list - \o \c MceVibrator connects to the MCE service and can start a certain + \li \c MceVibrator connects to the MCE service and can start a certain vibrator pattern. It also is responsible to parse the configuration file. - \o \c ButtonWidget provides a button for each pattern. Pressing the button + \li \c ButtonWidget provides a button for each pattern. Pressing the button activates the pattern in question. \endlist @@ -68,10 +68,10 @@ are available to us. \list - \o \c mceInterface is our D-Bus handle to the MCE service. We use it to + \li \c mceInterface is our D-Bus handle to the MCE service. We use it to invoke methods on the MCE request object. - \o \c lastPatternName contains the pattern that was activated last time. We + \li \c lastPatternName contains the pattern that was activated last time. We have to keep track of this, because the last pattern has to be deactivated before activating a new pattern. \endlist diff --git a/doc/src/examples/mandelbrot.qdoc b/doc/src/examples/mandelbrot.qdoc index 23e51ba637..a560766bdd 100644 --- a/doc/src/examples/mandelbrot.qdoc +++ b/doc/src/examples/mandelbrot.qdoc @@ -66,9 +66,9 @@ \table \row - \o \inlineimage mandelbrot_zoom1.png - \o \inlineimage mandelbrot_zoom2.png - \o \inlineimage mandelbrot_zoom3.png + \li \inlineimage mandelbrot_zoom1.png + \li \inlineimage mandelbrot_zoom2.png + \li \inlineimage mandelbrot_zoom3.png \endtable Similarly, when the user scrolls, the previous pixmap is scrolled @@ -77,17 +77,17 @@ \table \row - \o \inlineimage mandelbrot_scroll1.png - \o \inlineimage mandelbrot_scroll2.png - \o \inlineimage mandelbrot_scroll3.png + \li \inlineimage mandelbrot_scroll1.png + \li \inlineimage mandelbrot_scroll2.png + \li \inlineimage mandelbrot_scroll3.png \endtable The application consists of two classes: \list - \o \c RenderThread is a QThread subclass that renders + \li \c RenderThread is a QThread subclass that renders the Mandelbrot set. - \o \c MandelbrotWidget is a QWidget subclass that shows the + \li \c MandelbrotWidget is a QWidget subclass that shows the Mandelbrot set on screen and lets the user zoom and scroll. \endlist diff --git a/doc/src/examples/mousecalibration.qdoc b/doc/src/examples/mousecalibration.qdoc index b42d95956e..39b9140f28 100644 --- a/doc/src/examples/mousecalibration.qdoc +++ b/doc/src/examples/mousecalibration.qdoc @@ -39,8 +39,8 @@ The example consists of two classes in addition to the main program: \list - \o \c Calibration is a dialog widget that retrieves the device coordinates. - \o \c ScribbleWidget is a minimal drawing program used to let the user + \li \c Calibration is a dialog widget that retrieves the device coordinates. + \li \c ScribbleWidget is a minimal drawing program used to let the user test the new mouse settings. \endlist diff --git a/doc/src/examples/moveblocks.qdoc b/doc/src/examples/moveblocks.qdoc index d3332be834..38551abd28 100644 --- a/doc/src/examples/moveblocks.qdoc +++ b/doc/src/examples/moveblocks.qdoc @@ -40,14 +40,14 @@ The example consists of the following classes: \list - \o \c StateSwitcher inherits QState and can add + \li \c StateSwitcher inherits QState and can add \c {StateSwitchTransition}s to other states. When entered, it will randomly transition to one of these states. - \o \c StateSwitchTransition is a custom transition that + \li \c StateSwitchTransition is a custom transition that triggers on \c{StateSwitchEvent}s. - \o \c StateSwitchEvent is a QEvent that triggers \c{StateSwitchTransition}s. - \o \c QGraphicsRectWidget is a QGraphicsWidget that simply + \li \c StateSwitchEvent is a QEvent that triggers \c{StateSwitchTransition}s. + \li \c QGraphicsRectWidget is a QGraphicsWidget that simply paints its background in a solid \l{Qt::}{blue} color. \endlist diff --git a/doc/src/examples/orderform.qdoc b/doc/src/examples/orderform.qdoc index de967ecebd..94e4914444 100644 --- a/doc/src/examples/orderform.qdoc +++ b/doc/src/examples/orderform.qdoc @@ -161,21 +161,21 @@ \table \row - \o {1, 8} frame with \e{referenceFrameFormat} + \li {1, 8} frame with \e{referenceFrameFormat} \row - \o block \o \c{A company} + \li block \li \c{A company} \row - \o block + \li block \row - \o block \o \c{321 City Street} + \li block \li \c{321 City Street} \row - \o block + \li block \row - \o block \o \c{Industry Park} + \li block \li \c{Industry Park} \row - \o block + \li block \row - \o block \o \c{Another country} + \li block \li \c{Another country} \endtable This is accomplished with the following code: @@ -196,11 +196,11 @@ \table \row - \o block \o \c{Donald} + \li block \li \c{Donald} \row - \o block \o \c{47338 Park Avenue} + \li block \li \c{47338 Park Avenue} \row - \o block \o \c{Big City} + \li block \li \c{Big City} \endtable For spacing purposes, we invoke \l{QTextCursor::insertBlock()} @@ -221,21 +221,21 @@ \table \row - \o block + \li block \row - \o block + \li block \row - \o block \o \c{Date: 25 May 2007} + \li block \li \c{Date: 25 May 2007} \row - \o block + \li block \row - \o {1, 4} frame with \e{bodyFrameFormat} + \li {1, 4} frame with \e{bodyFrameFormat} \row - \o block \o \c{I would like to place an order for the following items:} + \li block \li \c{I would like to place an order for the following items:} \row - \o block + \li block \row - \o block + \li block \endtable A QTextTableFormat object, \c orderTableFormat, is used to hold the type @@ -257,27 +257,27 @@ \table \row - \o {1, 11} \c{orderTable} with \e{orderTableFormat} + \li {1, 11} \c{orderTable} with \e{orderTableFormat} \row - \o block \o \c{Product} + \li block \li \c{Product} \row - \o block \o \c{Quantity} + \li block \li \c{Quantity} \row - \o block \o \c{T-shirt} + \li block \li \c{T-shirt} \row - \o block \o \c{4} + \li block \li \c{4} \row - \o block \o \c{Badge} + \li block \li \c{Badge} \row - \o block \o \c{3} + \li block \li \c{3} \row - \o block \o \c{Reference book} + \li block \li \c{Reference book} \row - \o block \o \c{2} + \li block \li \c{2} \row - \o block \o \c{Coffee cup} + \li block \li \c{Coffee cup} \row - \o block \o \c{5} + \li block \li \c{5} \endtable The \c cursor is then moved back to \c{topFrame}'s @@ -296,19 +296,19 @@ \table \row - \o block + \li block \row - \o block\o \c{Please update my...} + \li block\li \c{Please update my...} \row - \o {1, 5} block + \li {1, 5} block \row - \o {1, 4} \c{offersTable} + \li {1, 4} \c{offersTable} \row - \o block \o \c{I want to receive...} + \li block \li \c{I want to receive...} \row - \o block \o \c{I do not want to receive...} + \li block \li \c{I do not want to receive...} \row - \o block \o \c{X} + \li block \li \c{X} \endtable The \c cursor is moved to insert "Sincerely" along with the customer's @@ -321,17 +321,17 @@ \table \row - \o block + \li block \row - \o {1, 5} block\o \c{Sincerely,} + \li {1, 5} block\li \c{Sincerely,} \row - \o block + \li block \row - \o block + \li block \row - \o block + \li block \row - \o block \o \c{Donald} + \li block \li \c{Donald} \endtable The \c createSample() function is used for illustration purposes, to create diff --git a/doc/src/examples/overpainting.qdoc b/doc/src/examples/overpainting.qdoc index 74f9f0a872..d20ee64698 100644 --- a/doc/src/examples/overpainting.qdoc +++ b/doc/src/examples/overpainting.qdoc @@ -214,30 +214,30 @@ calls, using the following approach: \list - \o Reimplement QGLWidget::initializeGL(), but only perform minimal + \li Reimplement QGLWidget::initializeGL(), but only perform minimal initialization. QPainter will perform its own initialization routines, modifying the matrix and property stacks, so it is better to defer certain initialization tasks until just before you render the 3D scene. - \o Reimplement QGLWidget::resizeGL() as in the pure 3D case. - \o Reimplement QWidget::paintEvent() to draw both 2D and 3D graphics. + \li Reimplement QGLWidget::resizeGL() as in the pure 3D case. + \li Reimplement QWidget::paintEvent() to draw both 2D and 3D graphics. \endlist The \l{QWidget::paintEvent()}{paintEvent()} implementation performs the following tasks: \list - \o Push the current OpenGL modelview matrix onto a stack. - \o Perform initialization tasks usually done in the + \li Push the current OpenGL modelview matrix onto a stack. + \li Perform initialization tasks usually done in the \l{QGLWidget::initializeGL()}{initializeGL()} function. - \o Perform code that would normally be located in the widget's + \li Perform code that would normally be located in the widget's \l{QGLWidget::resizeGL()}{resizeGL()} function to set the correct perspective transformation and set up the viewport. - \o Render the scene using OpenGL calls. - \o Pop the OpenGL modelview matrix off the stack. - \o Construct a QPainter object. - \o Initialize it for use on the widget with the QPainter::begin() function. - \o Draw primitives using QPainter's member functions. - \o Call QPainter::end() to finish painting. + \li Render the scene using OpenGL calls. + \li Pop the OpenGL modelview matrix off the stack. + \li Construct a QPainter object. + \li Initialize it for use on the widget with the QPainter::begin() function. + \li Draw primitives using QPainter's member functions. + \li Call QPainter::end() to finish painting. \endlist */ diff --git a/doc/src/examples/padnavigator.qdoc b/doc/src/examples/padnavigator.qdoc index 52d80adcb7..840c16b0c9 100644 --- a/doc/src/examples/padnavigator.qdoc +++ b/doc/src/examples/padnavigator.qdoc @@ -81,11 +81,11 @@ The private data members are: \list - \o \c pix: The optional pixmap that is drawn on top of the rectangle. - \o \c fillRect: Corresponds to the \c fill property. - \o \c color: The configurable gradient color fill of the rectangle. - \o \c bounds: The bounds of the rectangle. - \o \c gradient: A precalculated gradient used to fill the rectangle. + \li \c pix: The optional pixmap that is drawn on top of the rectangle. + \li \c fillRect: Corresponds to the \c fill property. + \li \c color: The configurable gradient color fill of the rectangle. + \li \c bounds: The bounds of the rectangle. + \li \c gradient: A precalculated gradient used to fill the rectangle. \endlist We will now review the \c RoundRectItem implementation. Let's start by @@ -320,13 +320,13 @@ QGraphicsRotation object for each of these. \list - \o \c flipRotation: Rotates the grid around its Qt::YAxis. This rotation is + \li \c flipRotation: Rotates the grid around its Qt::YAxis. This rotation is animated from 0 to 180, and eventually back, when enter is pressed on the keyboard, flipping the pad around. - \o \c xRotation: Rotates the grid around its Qt::XAxis. This is used to + \li \c xRotation: Rotates the grid around its Qt::XAxis. This is used to tilt the pad vertically corresponding to which item is currently selected. This way, the selected item is always kept in front. - \o \c yRotation: Rotates the grid around its Qt::YAxis. This is used to + \li \c yRotation: Rotates the grid around its Qt::YAxis. This is used to tilt the pad horizontally corresponding to which item is selected. This way, the selected item is always kept in front. \endlist @@ -391,11 +391,11 @@ values when flipped back: \list - \o \c smoothFlipRotation: Animates the main 180 degree rotation of the pad. - \o \c smoothFlipScale: Scales the pad out and then in again while the pad is rotating. - \o \c smoothFlipXRotation: Animates the selection item's X-tilt to 0 and back. - \o \c smoothFlipYRotation: Animates the selection item's Y-tilt to 0 and back. - \o \c flipAnimation: A parallel animation group that ensures all the above animations are run in parallel. + \li \c smoothFlipRotation: Animates the main 180 degree rotation of the pad. + \li \c smoothFlipScale: Scales the pad out and then in again while the pad is rotating. + \li \c smoothFlipXRotation: Animates the selection item's X-tilt to 0 and back. + \li \c smoothFlipYRotation: Animates the selection item's Y-tilt to 0 and back. + \li \c flipAnimation: A parallel animation group that ensures all the above animations are run in parallel. \endlist All animations are given a 500 millisecond duration and an @@ -433,10 +433,10 @@ states: \list - \o \c splashState: The initial state where the splash item is visible. - \o \c frontState: The base state where the splash is gone and we can see + \li \c splashState: The initial state where the splash item is visible. + \li \c frontState: The base state where the splash is gone and we can see the front side of the pad, and navigate the selection item. - \o \c backState: The flipped state where the \c backItem is visible, and we + \li \c backState: The flipped state where the \c backItem is visible, and we can interact with the QGraphicsProxyWidget-embedded form. \endlist @@ -531,18 +531,18 @@ The view toggles a few necessary properties: \list - \o It disables its scroll bars - this application has no use for scroll bars. - \o It assigns a minimum size. This is necessary to avoid numerical errors + \li It disables its scroll bars - this application has no use for scroll bars. + \li It assigns a minimum size. This is necessary to avoid numerical errors in our fit-in-view \c resizeEvent() implementation. - \o It sets \l{QGraphicsView::FullViewportUpdate}{FullViewportUpdate}, to + \li It sets \l{QGraphicsView::FullViewportUpdate}{FullViewportUpdate}, to ensure QGraphicsView doesn't spend time figuring out precisely what needs to be redrawn. This application is very simple - if anything changes, everything is updated. - \o It enables background caching - this makes no performance difference + \li It enables background caching - this makes no performance difference with OpenGL, but without OpenGL it avoids unnecessary re-scaling of the background pixmap. - \o It sets render hints that increase rendering quality. - \o If OpenGL is supported, a QGLWidget viewport is assigned to the view. + \li It sets render hints that increase rendering quality. + \li If OpenGL is supported, a QGLWidget viewport is assigned to the view. \endlist Finally, we start the state engine. diff --git a/doc/src/examples/painterpaths.qdoc b/doc/src/examples/painterpaths.qdoc index 868c4f5283..1bee28f029 100644 --- a/doc/src/examples/painterpaths.qdoc +++ b/doc/src/examples/painterpaths.qdoc @@ -48,9 +48,9 @@ The example consists of two classes: \list - \o The \c RenderArea class which is a custom widget displaying + \li The \c RenderArea class which is a custom widget displaying a single painter path. - \o The \c Window class which is the applications main window + \li The \c Window class which is the applications main window displaying several \c RenderArea widgets, and allowing the user to manipulate the painter paths' filling, pen, color and rotation angle. diff --git a/doc/src/examples/pixelator.qdoc b/doc/src/examples/pixelator.qdoc index 8eec198aba..6dff9e1b87 100644 --- a/doc/src/examples/pixelator.qdoc +++ b/doc/src/examples/pixelator.qdoc @@ -44,9 +44,9 @@ of standard views. To do this, we implement the following components: \list - \i A model which represents each pixel in an image as an item of data, where each + \li A model which represents each pixel in an image as an item of data, where each item contains a value for the brightness of the corresponding pixel. - \i A custom delegate that uses the information supplied by the model to represent + \li A custom delegate that uses the information supplied by the model to represent each pixel as a black circle on a white background, where the radius of the circle corresponds to the darkness of the pixel. \endlist diff --git a/doc/src/examples/plugandpaint.qdoc b/doc/src/examples/plugandpaint.qdoc index 118afa6a02..ee3f6fefe9 100644 --- a/doc/src/examples/plugandpaint.qdoc +++ b/doc/src/examples/plugandpaint.qdoc @@ -55,13 +55,13 @@ Plug & Paint consists of the following classes: \list - \o \c MainWindow is a QMainWindow subclass that provides the menu + \li \c MainWindow is a QMainWindow subclass that provides the menu system and that contains a \c PaintArea as the central widget. - \o \c PaintArea is a QWidget that allows the user to draw using a + \li \c PaintArea is a QWidget that allows the user to draw using a brush and to insert shapes. - \o \c PluginDialog is a dialog that shows information about the + \li \c PluginDialog is a dialog that shows information about the plugins detected by the application. - \o \c BrushInterface, \c ShapeInterface, and \c FilterInterface are + \li \c BrushInterface, \c ShapeInterface, and \c FilterInterface are abstract base classes that can be implemented by plugins to provide custom brushes, shapes, and image filters. \endlist @@ -321,10 +321,10 @@ plugin: \list 1 - \o Declare a plugin class. - \o Implement the interfaces provided by the plugin. - \o Export the plugin using the Q_EXPORT_PLUGIN2() macro. - \o Build the plugin using an adequate \c .pro file. + \li Declare a plugin class. + \li Implement the interfaces provided by the plugin. + \li Export the plugin using the Q_EXPORT_PLUGIN2() macro. + \li Build the plugin using an adequate \c .pro file. \endlist \section1 Declaration of the Plugin Class @@ -377,15 +377,15 @@ Then comes the brush-dependent part of the code: \list - \o If the brush is \gui{Pencil}, we just call + \li If the brush is \gui{Pencil}, we just call QPainter::drawLine() with the current QPen. - \o If the brush is \gui{Air Brush}, we start by setting the + \li If the brush is \gui{Air Brush}, we start by setting the painter's QBrush to Qt::Dense6Pattern to obtain a dotted pattern. Then we draw a circle filled with that QBrush several times, resulting in a thick line. - \o If the brush is \gui{Random Letters}, we draw a random letter + \li If the brush is \gui{Random Letters}, we draw a random letter at the new cursor position. Most of the code is for setting the font to be bold and larger than the default font and for computing an appropriate bounding rect. diff --git a/doc/src/examples/rogue.qdoc b/doc/src/examples/rogue.qdoc index 38c871c7db..44e371c667 100644 --- a/doc/src/examples/rogue.qdoc +++ b/doc/src/examples/rogue.qdoc @@ -64,10 +64,10 @@ The example consists of two classes: \list - \o \c Window draws the text display of the game and sets + \li \c Window draws the text display of the game and sets up the state machine. The window also has a status bar above the area in which the rouge moves. - \o \c MovementTransition is a transition that carries out + \li \c MovementTransition is a transition that carries out a single move of the rogue. \endlist diff --git a/doc/src/examples/screenshot.qdoc b/doc/src/examples/screenshot.qdoc index e99fe6cc19..7ee7ddb9c7 100644 --- a/doc/src/examples/screenshot.qdoc +++ b/doc/src/examples/screenshot.qdoc @@ -41,9 +41,9 @@ desktop. They are provided with a couple of options: \list - \o Delaying the screenshot, giving them time to rearrange + \li Delaying the screenshot, giving them time to rearrange their desktop. - \o Hiding the application's window while the screenshot is taken. + \li Hiding the application's window while the screenshot is taken. \endlist In addition the application allows the users to save their @@ -63,10 +63,10 @@ to facilitate the options: \list - \o The \c newScreenshot() slot prepares a new screenshot. - \o The \c saveScreenshot() slot saves the last screenshot. - \o The \c shootScreen() slot takes the screenshot. - \o The \c updateCheckBox() slot enables or disables the + \li The \c newScreenshot() slot prepares a new screenshot. + \li The \c saveScreenshot() slot saves the last screenshot. + \li The \c shootScreen() slot takes the screenshot. + \li The \c updateCheckBox() slot enables or disables the \gui {Hide This Window} option. \endlist diff --git a/doc/src/examples/scribble.qdoc b/doc/src/examples/scribble.qdoc index d9386843a5..5d801bf9cc 100644 --- a/doc/src/examples/scribble.qdoc +++ b/doc/src/examples/scribble.qdoc @@ -55,9 +55,9 @@ The example consists of two classes: \list - \o \c ScribbleArea is a custom widget that displays a QImage and + \li \c ScribbleArea is a custom widget that displays a QImage and allows to the user to draw on it. - \o \c MainWindow provides a menu above the \c ScribbleArea. + \li \c MainWindow provides a menu above the \c ScribbleArea. \endlist We will start by reviewing the \c ScribbleArea class. Then we will @@ -85,14 +85,14 @@ We also need the following private variables: \list - \o \c modified is \c true if there are unsaved + \li \c modified is \c true if there are unsaved changes to the image displayed in the scribble area. - \o \c scribbling is \c true while the user is pressing + \li \c scribbling is \c true while the user is pressing the left mouse button within the scribble area. - \o \c penWidth and \c penColor hold the currently + \li \c penWidth and \c penColor hold the currently set width and color for the pen used in the application. - \o \c image stores the image drawn by the user. - \o \c lastPoint holds the position of the cursor at the last + \li \c image stores the image drawn by the user. + \li \c lastPoint holds the position of the cursor at the last mouse press or mouse move event. \endlist @@ -176,18 +176,18 @@ good reasons for this: \list - \o The window system requires us to be able to redraw the widget + \li The window system requires us to be able to redraw the widget \e{at any time}. For example, if the window is minimized and restored, the window system might have forgotten the contents of the widget and send us a paint event. In other words, we can't rely on the window system to remember our image. - \o Qt normally doesn't allow us to paint outside of \c + \li Qt normally doesn't allow us to paint outside of \c paintEvent(). In particular, we can't paint from the mouse event handlers. (This behavior can be changed using the Qt::WA_PaintOnScreen widget attribute, though.) - \o If initialized properly, a QImage is guaranteed to use 8-bit + \li If initialized properly, a QImage is guaranteed to use 8-bit for each color channel (red, green, blue, and alpha), whereas a QWidget might have a lower color depth, depending on the monitor configuration. This means that if we load a 24-bit or diff --git a/doc/src/examples/simpletreemodel.qdoc b/doc/src/examples/simpletreemodel.qdoc index 36e0632eb2..ed584a3307 100644 --- a/doc/src/examples/simpletreemodel.qdoc +++ b/doc/src/examples/simpletreemodel.qdoc @@ -59,8 +59,8 @@ \target SimpleTreeModelStructure \table - \row \i \inlineimage treemodel-structure.png - \i \bold{Simple Tree Model Structure} + \row \li \inlineimage treemodel-structure.png + \li \b{Simple Tree Model Structure} The data is stored internally in the model using \c TreeItem objects that are linked together in a pointer-based tree structure. Generally, each @@ -101,14 +101,14 @@ structure. The functions provide the following features: \list - \o The \c appendChildItem() is used to add data when the model is first + \li The \c appendChildItem() is used to add data when the model is first constructed and is not used during normal use. - \o The \c child() and \c childCount() functions allow the model to obtain + \li The \c child() and \c childCount() functions allow the model to obtain information about any child items. - \o Information about the number of columns associated with the item is + \li Information about the number of columns associated with the item is provided by \c columnCount(), and the data in each column can be obtained with the data() function. - \o The \c row() and \c parent() functions are used to obtain the item's + \li The \c row() and \c parent() functions are used to obtain the item's row number and parent item. \endlist @@ -320,10 +320,10 @@ We process the text file with the following two rules: \list - \o For each pair of strings on each line, create an item (or node) + \li For each pair of strings on each line, create an item (or node) in a tree structure, and place each string in a column of data in the item. - \o When the first string on a line is indented with respect to the + \li When the first string on a line is indented with respect to the first string on the previous line, make the item a child of the previous item created. \endlist diff --git a/doc/src/examples/sipdialog.qdoc b/doc/src/examples/sipdialog.qdoc index 2b51af4fdc..b5f18cb4be 100644 --- a/doc/src/examples/sipdialog.qdoc +++ b/doc/src/examples/sipdialog.qdoc @@ -34,8 +34,8 @@ the Windows Mobile SIP (Software Input Panel) and reacts to it. \table - \row \o \inlineimage sipdialog-closed.png - \o \inlineimage sipdialog-opened.png + \row \li \inlineimage sipdialog-closed.png + \li \inlineimage sipdialog-opened.png \endtable Sometimes it is necessary for a dialog to take the SIP into account, @@ -90,10 +90,10 @@ The following signals are connected to their respective slots: \list - \o \c{button}'s \l{QPushButton::pressed()}{pressed()} signal to + \li \c{button}'s \l{QPushButton::pressed()}{pressed()} signal to \l{QApplication}'s \l{QApplication::closeAllWindows()} {closeAllWindows()} slot, - \o \l{QDesktopWidget}'s \l{QDesktopWidget::workAreaResized()} + \li \l{QDesktopWidget}'s \l{QDesktopWidget::workAreaResized()} {workAreaResized()} signal to \c{dialog}'s \c desktopResized() slot. \endlist diff --git a/doc/src/examples/sliders.qdoc b/doc/src/examples/sliders.qdoc index e71986bfc9..49d41a9d18 100644 --- a/doc/src/examples/sliders.qdoc +++ b/doc/src/examples/sliders.qdoc @@ -46,10 +46,10 @@ \list - \o \c SlidersGroup is a custom widget. It combines a QSlider, a + \li \c SlidersGroup is a custom widget. It combines a QSlider, a QScrollBar and a QDial. - \o \c Window is the main widget combining a QGroupBox and a + \li \c Window is the main widget combining a QGroupBox and a QStackedWidget. In this example, the QStackedWidget provides a stack of two \c SlidersGroup widgets. The QGroupBox contain several widgets that control the behavior of the slider-like @@ -122,10 +122,10 @@ slider-like widgets: \table - \header \o \o{2,1} QSlider \o{2,1} QScrollBar \o{2,1} QDial - \header \o \o Normal \o Inverted \o Normal \o Inverted \o Normal \o Inverted - \row \o Qt::Horizontal \o Left to right \o Right to left \o Left to right \o Right to left \o Clockwise \o Counterclockwise - \row \o Qt::Vertical \o Bottom to top \o Top to bottom \o Top to bottom \o Bottom to top \o Clockwise \o Counterclockwise + \header \li \li{2,1} QSlider \li{2,1} QScrollBar \li{2,1} QDial + \header \li \li Normal \li Inverted \li Normal \li Inverted \li Normal \li Inverted + \row \li Qt::Horizontal \li Left to right \li Right to left \li Left to right \li Right to left \li Clockwise \li Counterclockwise + \row \li Qt::Vertical \li Bottom to top \li Top to bottom \li Top to bottom \li Bottom to top \li Clockwise \li Counterclockwise \endtable It is common to invert the appearance of a vertical QSlider. A diff --git a/doc/src/examples/stardelegate.qdoc b/doc/src/examples/stardelegate.qdoc index 01507eaf82..c9cc1f40cf 100644 --- a/doc/src/examples/stardelegate.qdoc +++ b/doc/src/examples/stardelegate.qdoc @@ -58,15 +58,15 @@ The example consists of the following classes: \list - \o \c StarRating is the custom data type. It stores a rating + \li \c StarRating is the custom data type. It stores a rating expressed as stars, such as "2 out of 5 stars" or "5 out of 6 stars". - \o \c StarDelegate inherits QItemDelegate and provides support + \li \c StarDelegate inherits QItemDelegate and provides support for \c StarRating (in addition to the data types already handled by QItemDelegate). - \o \c StarEditor inherits QWidget and is used by \c StarDelegate + \li \c StarEditor inherits QWidget and is used by \c StarDelegate to let the user edit a star rating using the mouse. \endlist @@ -281,7 +281,7 @@ editor are: \list - \o It is possible to open editors programmatically by calling + \li It is possible to open editors programmatically by calling QAbstractItemView::edit(), instead of relying on edit triggers. This could be use to support other edit triggers than those offered by the QAbstractItemView::EditTrigger enum. @@ -289,7 +289,7 @@ item with the mouse might make sense as a way to pop up an editor. - \o By reimplementing QAbstractItemDelegate::editorEvent(), it is + \li By reimplementing QAbstractItemDelegate::editorEvent(), it is possible to implement the editor directly in the delegate, instead of creating a separate QWidget subclass. \endlist diff --git a/doc/src/examples/styles.qdoc b/doc/src/examples/styles.qdoc index 91fd1d54d7..d1f5091a4b 100644 --- a/doc/src/examples/styles.qdoc +++ b/doc/src/examples/styles.qdoc @@ -56,9 +56,9 @@ The example consists of the following classes: \list - \o \c NorwegianWoodStyle inherits from QMotifStyle and implements + \li \c NorwegianWoodStyle inherits from QMotifStyle and implements the Norwegian Wood style. - \o \c WidgetGallery is a \c QDialog subclass that shows the most + \li \c WidgetGallery is a \c QDialog subclass that shows the most common widgets and allows the user to switch style dynamically. \endlist @@ -91,16 +91,16 @@ resources}. \table - \row \o \inlineimage widgets/styles/images/woodbackground.png + \row \li \inlineimage widgets/styles/images/woodbackground.png - \o \bold{woodbackground.png} + \li \b{woodbackground.png} This texture is used as the background of most widgets. The wood pattern is horizontal. - \row \o \inlineimage widgets/styles/images/woodbutton.png + \row \li \inlineimage widgets/styles/images/woodbutton.png - \o \bold{woodbutton.png} + \li \b{woodbutton.png} This texture is used for filling push buttons and comboboxes. The wood pattern is vertical and more reddish @@ -261,17 +261,17 @@ them based on the state of the button: \list - \o If the button is a \l{QPushButton::flat}{flat button}, we use + \li If the button is a \l{QPushButton::flat}{flat button}, we use the \l{QPalette::Background}{Background} brush. We set \c darker to \c true if the button is \l{QAbstractButton::down}{down} or \l{QAbstractButton::checked}{checked}. - \o If the button is currently held down by the user or in the + \li If the button is currently held down by the user or in the \l{QAbstractButton::checked}{checked} state, we use the \l{QPalette::Mid}{Mid} component of the palette. We set \c darker to \c true if the button is \l{QAbstractButton::checked}{checked}. - \o Otherwise, we use the \l{QPalette::Button}{Button} component + \li Otherwise, we use the \l{QPalette::Button}{Button} component of the palette. \endlist diff --git a/doc/src/examples/svgalib.qdoc b/doc/src/examples/svgalib.qdoc index cac14a7469..f25a3e21a8 100644 --- a/doc/src/examples/svgalib.qdoc +++ b/doc/src/examples/svgalib.qdoc @@ -49,13 +49,13 @@ approach: \list 1 - \o \l {Step 1: Creating a Custom Graphics Driver} + \li \l {Step 1: Creating a Custom Graphics Driver} {Creating a Custom Graphics Driver} - \o \l {Step 2: Implementing a Custom Raster Paint Engine} + \li \l {Step 2: Implementing a Custom Raster Paint Engine} {Implementing a Custom Paint Engine} - \o \l {Step 3: Making the Widgets Aware of the Custom Paint + \li \l {Step 3: Making the Widgets Aware of the Custom Paint Engine}{Making the Widgets Aware of the Custom Paint Engine} \endlist @@ -69,8 +69,8 @@ \snippet doc/src/snippets/code/doc_src_examples_svgalib.qdoc 0 \table - \header \o SVGAlib - \row \o + \header \li SVGAlib + \row \li Instead of interfacing the graphics hardware directly, this example relies on \l {http://www.svgalib.org}{SVGAlib} being @@ -212,9 +212,9 @@ respectively. \table - \header \o Private Header Files + \header \li Private Header Files \row - \o + \li Note the \c include statement used by this class. The files prefixed with \c private/ are private headers file within @@ -285,9 +285,9 @@ adjustments of the graphics driver. \list - \o \l {Implementing a Custom Paint Device} - \o \l {Implementing a Custom Window Surface} - \o \l {Adjusting the Graphics Driver} + \li \l {Implementing a Custom Paint Device} + \li \l {Implementing a Custom Window Surface} + \li \l {Adjusting the Graphics Driver} \endlist \section2 Implementing a Custom Paint Device diff --git a/doc/src/examples/syntaxhighlighter.qdoc b/doc/src/examples/syntaxhighlighter.qdoc index d86719ab19..597a1a2bf3 100644 --- a/doc/src/examples/syntaxhighlighter.qdoc +++ b/doc/src/examples/syntaxhighlighter.qdoc @@ -40,9 +40,9 @@ The example consists of two classes: \list - \o The \c Highlighter class defines and applies the + \li The \c Highlighter class defines and applies the highlighting rules. - \o The \c MainWindow widget is the application's main window. + \li The \c MainWindow widget is the application's main window. \endlist We will first review the \c Highlighter class to see how you can diff --git a/doc/src/examples/tablet.qdoc b/doc/src/examples/tablet.qdoc index 249b593e9b..57fa7d5eca 100644 --- a/doc/src/examples/tablet.qdoc +++ b/doc/src/examples/tablet.qdoc @@ -61,15 +61,15 @@ The example consists of the following: \list - \o The \c MainWindow class inherits QMainWindow and creates + \li The \c MainWindow class inherits QMainWindow and creates the examples menus and connect their slots and signals. - \o The \c TabletCanvas class inherits QWidget and + \li The \c TabletCanvas class inherits QWidget and receives tablet events. It uses the events to paint on a offscreen pixmap, which it draws onto itself. - \o The \c TabletApplication class inherits QApplication. This + \li The \c TabletApplication class inherits QApplication. This class handles tablet events that are not sent to \c tabletEvent(). We will look at this later. - \o The \c main() function creates a \c MainWindow and shows it + \li The \c main() function creates a \c MainWindow and shows it as a top level window. \endlist diff --git a/doc/src/examples/tetrix.qdoc b/doc/src/examples/tetrix.qdoc index 1eb92a2a4a..fca5229ad8 100644 --- a/doc/src/examples/tetrix.qdoc +++ b/doc/src/examples/tetrix.qdoc @@ -53,11 +53,11 @@ This example shows how a simple game can be created using only three classes: \list - \o The \c TetrixWindow class is used to display the player's score, number of + \li The \c TetrixWindow class is used to display the player's score, number of lives, and information about the next piece to appear. - \o The \c TetrixBoard class contains the game logic, handles keyboard input, and + \li The \c TetrixBoard class contains the game logic, handles keyboard input, and displays the pieces on the playing area. - \o The \c TetrixPiece class contains information about each piece. + \li The \c TetrixPiece class contains information about each piece. \endlist In this approach, the \c TetrixBoard class is the most complex class, since it diff --git a/doc/src/examples/textfinder.qdoc b/doc/src/examples/textfinder.qdoc index 17c52c2208..8f1ed5d340 100644 --- a/doc/src/examples/textfinder.qdoc +++ b/doc/src/examples/textfinder.qdoc @@ -37,16 +37,16 @@ resource and is loaded into the display at startup. \table - \row \o \inlineimage textfinder-example-find.png - \o \inlineimage textfinder-example-find2.png + \row \li \inlineimage textfinder-example-find.png + \li \inlineimage textfinder-example-find2.png \endtable \section1 Setting Up The Resource File The resources required for Text Finder are: \list - \o \e{textfinder.ui} - the user interface file created in QtDesigner - \o \e{input.txt} - a text file containing some text to be displayed + \li \e{textfinder.ui} - the user interface file created in QtDesigner + \li \e{input.txt} - a text file containing some text to be displayed in the QTextEdit \endlist diff --git a/doc/src/examples/tooltips.qdoc b/doc/src/examples/tooltips.qdoc index d506268bd8..cfa1884097 100644 --- a/doc/src/examples/tooltips.qdoc +++ b/doc/src/examples/tooltips.qdoc @@ -53,8 +53,8 @@ The Tooltips example consists of two classes: \list - \o \c ShapeItem is a custom widget representing one single shape item. - \o \c SortingBox inherits from QWidget and is the application's main + \li \c ShapeItem is a custom widget representing one single shape item. + \li \c SortingBox inherits from QWidget and is the application's main widget. \endlist diff --git a/doc/src/examples/transformations.qdoc b/doc/src/examples/transformations.qdoc index 9a23c6c8e6..8bca26eb77 100644 --- a/doc/src/examples/transformations.qdoc +++ b/doc/src/examples/transformations.qdoc @@ -42,9 +42,9 @@ The example consists of two classes and a global enum: \list - \o The \c RenderArea class controls the rendering of a given shape. - \o The \c Window class is the application's main window. - \o The \c Operation enum describes the various transformation + \li The \c RenderArea class controls the rendering of a given shape. + \li The \c Window class is the application's main window. + \li The \c Operation enum describes the various transformation operations available in the application. \endlist diff --git a/doc/src/examples/trollprint.qdoc b/doc/src/examples/trollprint.qdoc index 4127348b39..63566bdc21 100644 --- a/doc/src/examples/trollprint.qdoc +++ b/doc/src/examples/trollprint.qdoc @@ -200,11 +200,11 @@ editor and follow these steps: \list - \o Uncomment the two lines that create a QLabel with the text + \li Uncomment the two lines that create a QLabel with the text "\TROLL PRINT\" in \c printpanel.cpp. - \o Word-tidying: Replace "2-sided" by "Two-sided" in \c printpanel.cpp. - \o Replace "1.0" with "1.1" everywhere it occurs in \c mainwindow.cpp. - \o Update the copyright year to 1999-2000 in \c mainwindow.cpp. + \li Word-tidying: Replace "2-sided" by "Two-sided" in \c printpanel.cpp. + \li Replace "1.0" with "1.1" everywhere it occurs in \c mainwindow.cpp. + \li Update the copyright year to 1999-2000 in \c mainwindow.cpp. \endlist (Of course the version number and copyright year would be consts or @@ -214,25 +214,25 @@ Linguist}. The following items are of special interest: \list - \o \c MainWindow + \li \c MainWindow \list - \o Troll Print 1.0 - marked "(obs.)", obsolete - \o About Troll Print 1.0 - marked "(obs.)", obsolete - \o Troll Print 1.0. Copyright 1999 Software, Inc. - + \li Troll Print 1.0 - marked "(obs.)", obsolete + \li About Troll Print 1.0 - marked "(obs.)", obsolete + \li Troll Print 1.0. Copyright 1999 Software, Inc. - marked obsolete - \o Troll Print 1.1 - automatically translated as + \li Troll Print 1.1 - automatically translated as "Troll Imprimir 1.1" - \o About Troll Print 1.1 - automatically translated as + \li About Troll Print 1.1 - automatically translated as "Troll Imprimir 1.1" - \o Troll Print 1.1. Copyright 1999-2000 Software, + \li Troll Print 1.1. Copyright 1999-2000 Software, Inc. - automatically translated as "Troll Imprimir 1.1. Copyright 1999-2000 Software, Inc." \endlist - \o \c PrintPanel + \li \c PrintPanel \list - \o 2-sided - marked "(obs.)", obsolete - \o \TROLL PRINT\ - unmarked, i.e. untranslated - \o Two-sided - unmarked, i.e. untranslated. + \li 2-sided - marked "(obs.)", obsolete + \li \TROLL PRINT\ - unmarked, i.e. untranslated + \li Two-sided - unmarked, i.e. untranslated. \endlist \endlist diff --git a/doc/src/examples/undoframework.qdoc b/doc/src/examples/undoframework.qdoc index 36e43f2ed8..0bc2efd025 100644 --- a/doc/src/examples/undoframework.qdoc +++ b/doc/src/examples/undoframework.qdoc @@ -61,18 +61,18 @@ The example consists of the following classes: \list - \o \c MainWindow is the main window and arranges the + \li \c MainWindow is the main window and arranges the example's widgets. It creates the commands based on user input and keeps them on the command stack. - \o \c AddCommand adds an item to the scene. - \o \c DeleteCommand deletes an item from the scene. - \o \c MoveCommand when an item is moved the MoveCommand keeps record + \li \c AddCommand adds an item to the scene. + \li \c DeleteCommand deletes an item from the scene. + \li \c MoveCommand when an item is moved the MoveCommand keeps record of the start and stop positions of the move, and it moves the item according to these when \c redo() and \c undo() is called. - \o \c DiagramScene inherits QGraphicsScene and + \li \c DiagramScene inherits QGraphicsScene and emits signals for the \c MoveComands when an item is moved. - \o \c DiagramItem inherits QGraphicsPolygonItem and represents + \li \c DiagramItem inherits QGraphicsPolygonItem and represents an item in the diagram. \endlist diff --git a/doc/src/examples/wiggly.qdoc b/doc/src/examples/wiggly.qdoc index 739f14d623..677e8b08ca 100644 --- a/doc/src/examples/wiggly.qdoc +++ b/doc/src/examples/wiggly.qdoc @@ -48,10 +48,10 @@ The example consists of two classes: \list - \o \c WigglyWidget is the custom widget displaying the text + \li \c WigglyWidget is the custom widget displaying the text in a wiggly line. - \o \c Dialog is the dialog widget allowing the user to enter a + \li \c Dialog is the dialog widget allowing the user to enter a text. It combines a \c WigglyWidget and a \c QLineEdit. \endlist diff --git a/doc/src/examples/windowflags.qdoc b/doc/src/examples/windowflags.qdoc index e39e4eddc7..09dc45c27f 100644 --- a/doc/src/examples/windowflags.qdoc +++ b/doc/src/examples/windowflags.qdoc @@ -46,10 +46,10 @@ The example consists of two classes: \list - \o \c ControllerWindow is the main application widget that allows + \li \c ControllerWindow is the main application widget that allows the user to choose among the available window flags, and displays the effect on a separate preview window. - \o \c PreviewWindow is a custom widget displaying the name of + \li \c PreviewWindow is a custom widget displaying the name of its currently set window flags in a read-only text editor. \endlist diff --git a/doc/src/gui/coordsys.qdoc b/doc/src/gui/coordsys.qdoc index ae1506ddd8..655dbf7cf3 100644 --- a/doc/src/gui/coordsys.qdoc +++ b/doc/src/gui/coordsys.qdoc @@ -67,11 +67,11 @@ \table \row - \o \inlineimage coordinatesystem-rect.png - \o \inlineimage coordinatesystem-line.png + \li \inlineimage coordinatesystem-rect.png + \li \inlineimage coordinatesystem-line.png \row - \o QRect(1, 2, 6, 4) - \o QLine(2, 7, 6, 1) + \li QRect(1, 2, 6, 4) + \li QLine(2, 7, 6, 1) \endtable \section2 Aliased Painting @@ -92,14 +92,14 @@ \table \row - \o \inlineimage coordinatesystem-rect-raster.png - \o \inlineimage coordinatesystem-line-raster.png + \li \inlineimage coordinatesystem-rect-raster.png + \li \inlineimage coordinatesystem-line-raster.png \row - \o + \li \snippet doc/src/snippets/code/doc_src_coordsys.cpp 0 - \o + \li \snippet doc/src/snippets/code/doc_src_coordsys.cpp 1 \endtable @@ -112,19 +112,19 @@ \table \header - \o {3,1} QRectF + \li {3,1} QRectF \row - \o \inlineimage qrect-diagram-zero.png - \o \inlineimage qrectf-diagram-one.png + \li \inlineimage qrect-diagram-zero.png + \li \inlineimage qrectf-diagram-one.png \row - \o Logical representation - \o One pixel wide pen + \li Logical representation + \li One pixel wide pen \row - \o \inlineimage qrectf-diagram-two.png - \o \inlineimage qrectf-diagram-three.png + \li \inlineimage qrectf-diagram-two.png + \li \inlineimage qrectf-diagram-three.png \row - \o Two pixel wide pen - \o Three pixel wide pen + \li Two pixel wide pen + \li Three pixel wide pen \endtable Note that for historical reasons the return value of the @@ -158,14 +158,14 @@ \table \row - \o \inlineimage coordinatesystem-rect-antialias.png - \o \inlineimage coordinatesystem-line-antialias.png + \li \inlineimage coordinatesystem-rect-antialias.png + \li \inlineimage coordinatesystem-line-antialias.png \row - \o + \li \snippet doc/src/snippets/code/doc_src_coordsys.cpp 2 - \o + \li \snippet doc/src/snippets/code/doc_src_coordsys.cpp 3 \endtable @@ -183,15 +183,15 @@ \table \row - \o \inlineimage qpainter-clock.png - \o \inlineimage qpainter-rotation.png - \o \inlineimage qpainter-scale.png - \o \inlineimage qpainter-translation.png + \li \inlineimage qpainter-clock.png + \li \inlineimage qpainter-rotation.png + \li \inlineimage qpainter-scale.png + \li \inlineimage qpainter-translation.png \row - \o nop - \o \l {QPainter::rotate()}{rotate()} - \o \l {QPainter::scale()}{scale()} - \o \l {QPainter::translate()}{translate()} + \li nop + \li \l {QPainter::rotate()}{rotate()} + \li \l {QPainter::scale()}{scale()} + \li \l {QPainter::translate()}{translate()} \endtable You can also twist the coordinate system around the origin using @@ -218,10 +218,10 @@ \table 100% \header - \o {2,1} Analog Clock Example + \li {2,1} Analog Clock Example \row - \o \inlineimage coordinatesystem-analogclock.png - \o + \li \inlineimage coordinatesystem-analogclock.png + \li The Analog Clock example shows how to draw the contents of a custom widget using QPainter's transformation matrix. @@ -236,7 +236,7 @@ sizes. \row - \o {2,1} + \li {2,1} \snippet examples/widgets/analogclock/analogclock.cpp 9 @@ -368,23 +368,23 @@ QPaintDevice, and QPaintEngine classes: \table - \header \o Class \o Description + \header \li Class \li Description \row - \o QPainter - \o + \li QPainter + \li The QPainter class performs low-level painting on widgets and other paint devices. QPainter can operate on any object that inherits the QPaintDevice class, using the same code. \row - \o QPaintDevice - \o + \li QPaintDevice + \li The QPaintDevice class is the base class of objects that can be painted. Qt provides several devices: QWidget, QImage, QPixmap, QPrinter and QPicture, and other devices can also be defined by subclassing QPaintDevice. \row - \o QPaintEngine - \o + \li QPaintEngine + \li The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a given platform. Qt 4 provides several premade implementations of QPaintEngine for the @@ -397,10 +397,10 @@ using the QTransform class: \table - \header \o Class \o Description + \header \li Class \li Description \row - \o QTransform - \o + \li QTransform + \li A 3 x 3 transformation matrix. Use QTransform to rotate, shear, scale, or translate the coordinate system. \endtable @@ -411,45 +411,45 @@ name is suffixed with an \c F. \table - \header \o Class \o Description + \header \li Class \li Description \row - \o \l{QPoint}(\l{QPointF}{F}) - \o + \li \l{QPoint}(\l{QPointF}{F}) + \li A single 2D point in the coordinate system. Most functions in Qt that deal with points can accept either a QPoint, a QPointF, two \c{int}s, or two \c{qreal}s. \row - \o \l{QSize}(\l{QSizeF}{F}) - \o + \li \l{QSize}(\l{QSizeF}{F}) + \li A single 2D vector. Internally, QPoint and QSize are the same, but a point is not the same as a size, so both classes exist. Again, most functions accept either QSizeF, a QSize, two \c{int}s, or two \c{qreal}s. \row - \o \l{QRect}(\l{QRectF}{F}) - \o + \li \l{QRect}(\l{QRectF}{F}) + \li A 2D rectangle. Most functions accept either a QRectF, a QRect, four \c{int}s, or four \c {qreal}s. \row - \o \l{QLine}(\l{QLineF}{F}) - \o + \li \l{QLine}(\l{QLineF}{F}) + \li A 2D finite-length line, characterized by a start point and an end point. \row - \o \l{QPolygon}(\l{QPolygonF}{F}) - \o + \li \l{QPolygon}(\l{QPolygonF}{F}) + \li A 2D polygon. A polygon is a vector of \c{QPoint(F)}s. If the first and last points are the same, the polygon is closed. \row - \o QPainterPath - \o + \li QPainterPath + \li A vectorial specification of a 2D shape. Painter paths are the ultimate painting primitive, in the sense that any shape (rectange, ellipse, spline) or combination of shapes can be expressed as a path. A path specifies both an outline and an area. \row - \o QRegion - \o + \li QRegion + \li An area in a paint device, expressed as a list of \l{QRect}s. In general, we recommend using the vectorial QPainterPath class instead of QRegion for specifying areas, diff --git a/doc/src/gui/paintsystem.qdoc b/doc/src/gui/paintsystem.qdoc index f9670ff5d8..4b33e4fed3 100644 --- a/doc/src/gui/paintsystem.qdoc +++ b/doc/src/gui/paintsystem.qdoc @@ -74,13 +74,13 @@ \section1 Topics \list - \o \l{Classes for Painting} - \o \l{Paint Devices and Backends} - \o \l{Drawing and Filling} - \o \l{Coordinate System} - \o \l{Reading and Writing Image Files} - \o \l{Styling} - \o \l{Printing with Qt} + \li \l{Classes for Painting} + \li \l{Paint Devices and Backends} + \li \l{Drawing and Filling} + \li \l{Coordinate System} + \li \l{Reading and Writing Image Files} + \li \l{Styling} + \li \l{Printing with Qt} \endlist \section1 Classes for Painting @@ -115,14 +115,14 @@ \image paintsystem-devices.png \table 100% - \row \o \bold Widget + \row \li \b Widget The QWidget class is the base class of all user interface objects. The widget is the atom of the user interface: it receives mouse, keyboard and other events from the window system, and paints a representation of itself on the screen. - \row \o \bold Image + \row \li \b Image The QImage class provides a hardware-independent image representation which is designed and optimized for I/O, and for @@ -136,7 +136,7 @@ painting can be performed in another thread than the current GUI thread. - \row \o \bold Pixmap + \row \li \b Pixmap The QPixmap class is an off-screen image representation which is designed and optimized for showing images on screen. Unlike @@ -156,7 +156,7 @@ constructing QRegion objects, and for setting masks for pixmaps and widgets. - \row \o \bold {OpenGL Widget} + \row \li \b {OpenGL Widget} As mentioned previously, Qt provides the QtOpenGL module offering classes that makes it easy to use OpenGL in Qt applications. For @@ -169,7 +169,7 @@ most drawing operations, such as transformations and pixmap drawing. - \row \o \bold {Pixel Buffer} + \row \li \b {Pixel Buffer} The QtOpenGL module also provides the QGLPixelBuffer class which inherits QPaintDevice directly. @@ -178,7 +178,7 @@ pbuffer is normally done using full hardware acceleration which can be significantly faster than rendering into a QPixmap. - \row \o \bold {Framebuffer Object} + \row \li \b {Framebuffer Object} The QtOpenGL module also provides the QGLFramebufferObject class which inherits QPaintDevice directly. @@ -188,7 +188,7 @@ offer several advantages over pixel buffers for this purpose. These are described in the QGLFramebufferObject class documentation. - \row \o \bold {Picture} + \row \li \b {Picture} The QPicture class is a paint device that records and replays QPainter commands. A picture serializes painter commands to an IO @@ -200,7 +200,7 @@ Qt provides the QPicture::load() and QPicture::save() functions as well as streaming operators for loading and saving pictures. - \row \o \bold {Printer} + \row \li \b {Printer} The QPrinter class is a paint device that paints on a printer. On Windows or Mac OS X, QPrinter uses the built-in printer @@ -218,7 +218,7 @@ to QPrinter::PdfFormat, QPrinter will generate its output as a PDF file. - \row \o \bold {Custom Backends} + \row \li \b {Custom Backends} Support for a new backend can be implemented by deriving from the QPaintDevice class and reimplementing the virtual @@ -238,17 +238,17 @@ \table \row - \o Windows - \o Software Rasterizer + \li Windows + \li Software Rasterizer \row - \o X11 - \o X11 + \li X11 + \li X11 \row - \o Mac OS X - \o CoreGraphics + \li Mac OS X + \li CoreGraphics \row - \o Embedded - \o Software Rasterizer + \li Embedded + \li Software Rasterizer \endtable Passing a command line parameter to the application, such as, @@ -289,8 +289,8 @@ \table 100% \row - \o \image paintsystem-painterpath.png - \o \bold QPainterPath + \li \image paintsystem-painterpath.png + \li \b QPainterPath A painter path is an object composed of lines and curves. For example, a rectangle is composed by lines and an ellipse is @@ -333,8 +333,8 @@ pixels, and the benefits of anti-aliased painting. \table 100% - \row \o - \bold {Anti-Aliased Painting} + \row \li + \b {Anti-Aliased Painting} When drawing, the pixel rendering is controlled by the QPainter::Antialiasing render hint. The QPainter::RenderHint enum @@ -345,7 +345,7 @@ antialias edges of primitives if possible, i.e. smoothing the edges by using different color intensities. - \o \image paintsystem-antialiasing.png + \li \image paintsystem-antialiasing.png \endtable @@ -376,8 +376,8 @@ \table 100% \row - \o \image paintsystem-fancygradient.png - \o \bold QGradient + \li \image paintsystem-fancygradient.png + \li \b QGradient The QGradient class is used in combination with QBrush to specify gradient fills. @@ -416,14 +416,14 @@ \table 100% \row - \o \bold QMovie + \li \b QMovie QMovie is a convenience class for displaying animations, using the QImageReader class internally. Once created, the QMovie class provides various functions for both running and controlling the given animation. - \o \image paintsystem-movie.png + \li \image paintsystem-movie.png \endtable The QImageReader and QImageWriter classes rely on the @@ -450,8 +450,8 @@ \table 100% \row - \o \image paintsystem-svg.png - \o \bold {SVG Rendering} + \li \image paintsystem-svg.png + \li \b {SVG Rendering} Scalable Vector Graphics (SVG) is a language for describing two-dimensional graphics and graphical applications in XML. SVG 1.1 is a W3C Recommendation @@ -513,10 +513,10 @@ Most functions for drawing style elements take four arguments: \list - \o an enum value specifying which graphical element to draw - \o a QStyleOption object specifying how and where to render that element - \o a QPainter object that should be used to draw the element - \o a QWidget object on which the drawing is performed (optional) + \li an enum value specifying which graphical element to draw + \li a QStyleOption object specifying how and where to render that element + \li a QPainter object that should be used to draw the element + \li a QWidget object on which the drawing is performed (optional) \endlist The style gets all the information it needs to render the @@ -538,8 +538,8 @@ \table 100% \row - \o \inlineimage paintsystem-icon.png - \o \bold QIcon + \li \inlineimage paintsystem-icon.png + \li \b QIcon The QIcon class provides scalable icons in different modes and states. diff --git a/doc/src/network/files-and-resources/datastreamformat.qdoc b/doc/src/network/files-and-resources/datastreamformat.qdoc index 97cadac93e..17a0044a69 100644 --- a/doc/src/network/files-and-resources/datastreamformat.qdoc +++ b/doc/src/network/files-and-resources/datastreamformat.qdoc @@ -43,326 +43,326 @@ the application happens to be running on. \table - \row \o bool - \o \list - \o boolean - \endlist - \row \o qint8 - \o \list - \o signed byte - \endlist - \row \o qint16 - \o \list - \o signed 16-bit integer - \endlist - \row \o qint32 - \o \list - \o signed 32-bit integer - \endlist - \row \o qint64 - \o \list - \o signed 64-bit integer - \endlist - \row \o quint8 - \o \list - \o unsigned byte - \endlist - \row \o quint16 - \o \list - \o unsigned 16-bit integer - \endlist - \row \o quint32 - \o \list - \o unsigned 32-bit integer - \endlist - \row \o quint64 - \o \list - \o unsigned 64-bit integer - \endlist - \row \o \c float - \o \list - \o 32-bit floating point number using the standard IEEE 754 format - \endlist - \row \o \c double - \o \list - \o 64-bit floating point number using the standard IEEE 754 format - \endlist - \row \o \c {const char *} - \o \list - \o The string length (quint32) - \o The string bytes, excluding the terminating 0 - \endlist - \row \o QBitArray - \o \list - \o The array size (quint32) - \o The array bits, i.e. (size + 7)/8 bytes - \endlist - \row \o QBrush - \o \list - \o The brush style (quint8) - \o The brush color (QColor) - \o If style is CustomPattern, the brush pixmap (QPixmap) - \endlist - \row \o QByteArray - \o \list - \o If the byte array is null: 0xFFFFFFFF (quint32) - \o Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes - \endlist - \row \o \l QColor - \o \list - \o Color spec (qint8) - \o Alpha value (quint16) - \o Red value (quint16) - \o Green value (quint16) - \o Blue value (quint16) - \o Pad value (quint16) - \endlist - \row \o QCursor - \o \list - \o Shape ID (qint16) - \o If shape is BitmapCursor: The bitmap (QPixmap), mask (QPixmap), and hot spot (QPoint) - \endlist - \row \o QDate - \o \list - \o Julian day (quint32) - \endlist - \row \o QDateTime - \o \list - \o Date (QDate) - \o Time (QTime) - \o 0 for Qt::LocalTime, 1 for Qt::UTC (quint8) - \endlist - \row \o QEasingCurve - \o \list - \o type (quint8) - \o func (quint64) - \o hasConfig (bool) - \o If hasConfig is true then these fields follow: - \o list - \o period (double) - \o amplitude (double) - \o overshoot (double) - \endlist - \row \o QFont - \o \list - \o The family (QString) - \o The point size (qint16) - \o The style hint (quint8) - \o The char set (quint8) - \o The weight (quint8) - \o The font bits (quint8) - \endlist - \row \o QHash - \o \list - \o The number of items (quint32) - \o For all items, the key (Key) and value (T) - \endlist - \row \o QIcon - \o \list - \o The number of pixmap entries (quint32) - \o For all pixmap entries: + \row \li bool + \li \list + \li boolean + \endlist + \row \li qint8 + \li \list + \li signed byte + \endlist + \row \li qint16 + \li \list + \li signed 16-bit integer + \endlist + \row \li qint32 + \li \list + \li signed 32-bit integer + \endlist + \row \li qint64 + \li \list + \li signed 64-bit integer + \endlist + \row \li quint8 + \li \list + \li unsigned byte + \endlist + \row \li quint16 + \li \list + \li unsigned 16-bit integer + \endlist + \row \li quint32 + \li \list + \li unsigned 32-bit integer + \endlist + \row \li quint64 + \li \list + \li unsigned 64-bit integer + \endlist + \row \li \c float + \li \list + \li 32-bit floating point number using the standard IEEE 754 format + \endlist + \row \li \c double + \li \list + \li 64-bit floating point number using the standard IEEE 754 format + \endlist + \row \li \c {const char *} + \li \list + \li The string length (quint32) + \li The string bytes, excluding the terminating 0 + \endlist + \row \li QBitArray + \li \list + \li The array size (quint32) + \li The array bits, i.e. (size + 7)/8 bytes + \endlist + \row \li QBrush + \li \list + \li The brush style (quint8) + \li The brush color (QColor) + \li If style is CustomPattern, the brush pixmap (QPixmap) + \endlist + \row \li QByteArray + \li \list + \li If the byte array is null: 0xFFFFFFFF (quint32) + \li Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes + \endlist + \row \li \l QColor + \li \list + \li Color spec (qint8) + \li Alpha value (quint16) + \li Red value (quint16) + \li Green value (quint16) + \li Blue value (quint16) + \li Pad value (quint16) + \endlist + \row \li QCursor + \li \list + \li Shape ID (qint16) + \li If shape is BitmapCursor: The bitmap (QPixmap), mask (QPixmap), and hot spot (QPoint) + \endlist + \row \li QDate + \li \list + \li Julian day (quint32) + \endlist + \row \li QDateTime + \li \list + \li Date (QDate) + \li Time (QTime) + \li 0 for Qt::LocalTime, 1 for Qt::UTC (quint8) + \endlist + \row \li QEasingCurve + \li \list + \li type (quint8) + \li func (quint64) + \li hasConfig (bool) + \li If hasConfig is true then these fields follow: + \li list + \li period (double) + \li amplitude (double) + \li overshoot (double) + \endlist + \row \li QFont + \li \list + \li The family (QString) + \li The point size (qint16) + \li The style hint (quint8) + \li The char set (quint8) + \li The weight (quint8) + \li The font bits (quint8) + \endlist + \row \li QHash + \li \list + \li The number of items (quint32) + \li For all items, the key (Key) and value (T) + \endlist + \row \li QIcon + \li \list + \li The number of pixmap entries (quint32) + \li For all pixmap entries: \list - \o The pixmap (QPixmap) - \o The file name (QString) - \o The pixmap size (QSize) - \o The \l{QIcon::Mode}{mode} (quint32) - \o The \l{QIcon::State}{state} (quint32) + \li The pixmap (QPixmap) + \li The file name (QString) + \li The pixmap size (QSize) + \li The \l{QIcon::Mode}{mode} (quint32) + \li The \l{QIcon::State}{state} (quint32) \endlist \endlist - \row \o QImage - \o \list - \o If the image is null a "null image" marker is saved; + \row \li QImage + \li \list + \li If the image is null a "null image" marker is saved; otherwise the image is saved in PNG or BMP format (depending on the stream version). If you want control of the format, stream the image into a QBuffer (using QImageIO) and stream that. \endlist - \row \o QKeySequence - \o \list - \o A QList, where each integer is a key in the key sequence - \endlist - \row \o QLinkedList - \o \list - \o The number of items (quint32) - \o The items (T) - \endlist - \row \o QList - \o \list - \o The number of items (quint32) - \o The items (T) - \endlist - \row \o QMap - \o \list - \o The number of items (quint32) - \o For all items, the key (Key) and value (T) - \endlist - \row \o QMargins - \o \list - \o left (int) - \o top (int) - \o right (int) - \o bottom (int) - \endlist - \row \o QMatrix - \o \list - \o m11 (double) - \o m12 (double) - \o m21 (double) - \o m22 (double) - \o dx (double) - \o dy (double) - \endlist - \row \o QMatrix4x4 - \o \list - \o m11 (double) - \o m12 (double) - \o m13 (double) - \o m14 (double) - \o m21 (double) - \o m22 (double) - \o m23 (double) - \o m24 (double) - \o m31 (double) - \o m32 (double) - \o m33 (double) - \o m34 (double) - \o m41 (double) - \o m42 (double) - \o m43 (double) - \o m44 (double) - \endlist - \row \o QPair - \o \list - \o first (T1) - \o second (T2) - \endlist - \row \o QPalette - \o The disabled, active, and inactive color groups, each of which consists + \row \li QKeySequence + \li \list + \li A QList, where each integer is a key in the key sequence + \endlist + \row \li QLinkedList + \li \list + \li The number of items (quint32) + \li The items (T) + \endlist + \row \li QList + \li \list + \li The number of items (quint32) + \li The items (T) + \endlist + \row \li QMap + \li \list + \li The number of items (quint32) + \li For all items, the key (Key) and value (T) + \endlist + \row \li QMargins + \li \list + \li left (int) + \li top (int) + \li right (int) + \li bottom (int) + \endlist + \row \li QMatrix + \li \list + \li m11 (double) + \li m12 (double) + \li m21 (double) + \li m22 (double) + \li dx (double) + \li dy (double) + \endlist + \row \li QMatrix4x4 + \li \list + \li m11 (double) + \li m12 (double) + \li m13 (double) + \li m14 (double) + \li m21 (double) + \li m22 (double) + \li m23 (double) + \li m24 (double) + \li m31 (double) + \li m32 (double) + \li m33 (double) + \li m34 (double) + \li m41 (double) + \li m42 (double) + \li m43 (double) + \li m44 (double) + \endlist + \row \li QPair + \li \list + \li first (T1) + \li second (T2) + \endlist + \row \li QPalette + \li The disabled, active, and inactive color groups, each of which consists of the following: \list - \o foreground (QBrush) - \o button (QBrush) - \o light (QBrush) - \o midlight (QBrush) - \o dark (QBrush) - \o mid (QBrush) - \o text (QBrush) - \o brightText (QBrush) - \o buttonText (QBrush) - \o base (QBrush) - \o background (QBrush) - \o shadow (QBrush) - \o highlight (QBrush) - \o highlightedText (QBrush) - \o link (QBrush) - \o linkVisited (QBrush) - \endlist - \row \o QPen - \o \list - \o The pen styles (quint8) - \o The pen width (quint16) - \o The pen color (QColor) - \endlist - \row \o QPicture - \o \list - \o The size of the picture data (quint32) - \o The raw bytes of picture data (char) - \endlist - \row \o QPixmap - \o \list - \o Save it as a PNG image. - \endlist - \row \o QPoint - \o \list - \o The x coordinate (qint32) - \o The y coordinate (qint32) - \endlist - \row \o QQuaternion - \o \list - \o The scalar component (double) - \o The x coordinate (double) - \o The y coordinate (double) - \o The z coordinate (double) - \endlist - \row \o QRect - \o \list - \o left (qint32) - \o top (qint32) - \o right (qint32) - \o bottom (qint32) - \endlist - \row \o QRegExp - \o \list - \o The regexp pattern (QString) - \o Case sensitivity (quint8) - \o Regular expression syntax (quint8) - \o Minimal matching (quint8) - \endlist - \row \o QRegion - \o \list - \o The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32) - \o 10 (qint32) - \o The number of rectangles (quint32) - \o The rectangles in sequential order (QRect) - \endlist - \row \o QSize - \o \list - \o width (qint32) - \o height (qint32) - \endlist - \row \o QString - \o \list - \o If the string is null: 0xFFFFFFFF (quint32) - \o Otherwise: The string length in bytes (quint32) followed by the data in UTF-16 - \endlist - \row \o QTime - \o \list - \o Milliseconds since midnight (quint32) - \endlist - \row \o QTransform - \o \list - \o m11 (double) - \o m12 (double) - \o m13 (double) - \o m21 (double) - \o m22 (double) - \o m23 (double) - \o m31 (double) - \o m32 (double) - \o m33 (double) - \endlist - \row \o QUrl - \o \list - \o Holds an URL (QString) - \endlist - \row \o QVariant - \o \list - \o The type of the data (quint32) - \o The null flag (qint8) - \o The data of the specified type - \endlist - \row \o QVector2D - \o \list - \o the x coordinate (double) - \o the y coordinate (double) - \endlist - \row \o QVector3D - \o \list - \o the x coordinate (double) - \o the y coordinate (double) - \o the z coordinate (double) - \endlist - \row \o QVector4D - \o \list - \o the x coordinate (double) - \o the y coordinate (double) - \o the z coordinate (double) - \o the w coordinate (double) - \endlist - \row \o QVector - \o \list - \o The number of items (quint32) - \o The items (T) + \li foreground (QBrush) + \li button (QBrush) + \li light (QBrush) + \li midlight (QBrush) + \li dark (QBrush) + \li mid (QBrush) + \li text (QBrush) + \li brightText (QBrush) + \li buttonText (QBrush) + \li base (QBrush) + \li background (QBrush) + \li shadow (QBrush) + \li highlight (QBrush) + \li highlightedText (QBrush) + \li link (QBrush) + \li linkVisited (QBrush) + \endlist + \row \li QPen + \li \list + \li The pen styles (quint8) + \li The pen width (quint16) + \li The pen color (QColor) + \endlist + \row \li QPicture + \li \list + \li The size of the picture data (quint32) + \li The raw bytes of picture data (char) + \endlist + \row \li QPixmap + \li \list + \li Save it as a PNG image. + \endlist + \row \li QPoint + \li \list + \li The x coordinate (qint32) + \li The y coordinate (qint32) + \endlist + \row \li QQuaternion + \li \list + \li The scalar component (double) + \li The x coordinate (double) + \li The y coordinate (double) + \li The z coordinate (double) + \endlist + \row \li QRect + \li \list + \li left (qint32) + \li top (qint32) + \li right (qint32) + \li bottom (qint32) + \endlist + \row \li QRegExp + \li \list + \li The regexp pattern (QString) + \li Case sensitivity (quint8) + \li Regular expression syntax (quint8) + \li Minimal matching (quint8) + \endlist + \row \li QRegion + \li \list + \li The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32) + \li 10 (qint32) + \li The number of rectangles (quint32) + \li The rectangles in sequential order (QRect) + \endlist + \row \li QSize + \li \list + \li width (qint32) + \li height (qint32) + \endlist + \row \li QString + \li \list + \li If the string is null: 0xFFFFFFFF (quint32) + \li Otherwise: The string length in bytes (quint32) followed by the data in UTF-16 + \endlist + \row \li QTime + \li \list + \li Milliseconds since midnight (quint32) + \endlist + \row \li QTransform + \li \list + \li m11 (double) + \li m12 (double) + \li m13 (double) + \li m21 (double) + \li m22 (double) + \li m23 (double) + \li m31 (double) + \li m32 (double) + \li m33 (double) + \endlist + \row \li QUrl + \li \list + \li Holds an URL (QString) + \endlist + \row \li QVariant + \li \list + \li The type of the data (quint32) + \li The null flag (qint8) + \li The data of the specified type + \endlist + \row \li QVector2D + \li \list + \li the x coordinate (double) + \li the y coordinate (double) + \endlist + \row \li QVector3D + \li \list + \li the x coordinate (double) + \li the y coordinate (double) + \li the z coordinate (double) + \endlist + \row \li QVector4D + \li \list + \li the x coordinate (double) + \li the y coordinate (double) + \li the z coordinate (double) + \li the w coordinate (double) + \endlist + \row \li QVector + \li \list + \li The number of items (quint32) + \li The items (T) \endlist \endtable */ diff --git a/doc/src/network/network-programming/bearermanagement.qdoc b/doc/src/network/network-programming/bearermanagement.qdoc index bcedc85a59..91dc32c5a5 100644 --- a/doc/src/network/network-programming/bearermanagement.qdoc +++ b/doc/src/network/network-programming/bearermanagement.qdoc @@ -81,16 +81,16 @@ lists the major QNetworkSession functions and how they fit into the session and hardware management categories: \table 60% -\header \o Interface management \o Session management -\row \o QNetworkSession::stop() \o QNetworkSession::open() -\row \o QNetworkSession::interface() \o QNetworkSession::close() -\row \o QNetworkSession::state() \o QNetworkSession::isOpen() -\row \o QNetworkSession::bytesWritten() \o QNetworkSession::migrate() -\row \o QNetworkSession::bytesReceived() \o QNetworkSession::ignore() -\row \o QNetworkSession::activeTime() \o QNetworkSession::accept() -\row \o QNetworkSession::stateChanged() \o QNetworkSession::reject() -\row \o \o QNetworkSession::opened() -\row \o \o QNetworkSession::closed() +\header \li Interface management \li Session management +\row \li QNetworkSession::stop() \li QNetworkSession::open() +\row \li QNetworkSession::interface() \li QNetworkSession::close() +\row \li QNetworkSession::state() \li QNetworkSession::isOpen() +\row \li QNetworkSession::bytesWritten() \li QNetworkSession::migrate() +\row \li QNetworkSession::bytesReceived() \li QNetworkSession::ignore() +\row \li QNetworkSession::activeTime() \li QNetworkSession::accept() +\row \li QNetworkSession::stateChanged() \li QNetworkSession::reject() +\row \li \li QNetworkSession::opened() +\row \li \li QNetworkSession::closed() \endtable The state of the session represents the state of the underlying access point @@ -242,27 +242,27 @@ determining the feature support: \table \header - \o Platform - \o Backend capabilities + \li Platform + \li Backend capabilities \row - \o Linux\unicode{0xAE} - \o Linux uses the \l {http://projects.gnome.org/NetworkManager}{NetworkManager} + \li Linux\unicode{0xAE} + \li Linux uses the \l {http://projects.gnome.org/NetworkManager}{NetworkManager} and \l {http://connman.net/}{ConnMan} / \l {http://ofono.org/}{oFono} APIs which support interface notifications and starting and stopping of network interfaces. \row - \o Windows\unicode{0xAE} XP - \o This platform supports interface notifications without active polling. + \li Windows\unicode{0xAE} XP + \li This platform supports interface notifications without active polling. \row - \o Windows XP SP2+Hotfixes, Windows XP SP3, Windows Vista, Windows 7 - \o In addition to standard Windows XP wifi access point monitoring has been improved which includes the ability to start and stop wifi interfaces. This requires Windows to manage the wifi interfaces. + \li Windows XP SP2+Hotfixes, Windows XP SP3, Windows Vista, Windows 7 + \li In addition to standard Windows XP wifi access point monitoring has been improved which includes the ability to start and stop wifi interfaces. This requires Windows to manage the wifi interfaces. \row - \o Mac OS\unicode{0xAE} - \o This platform has full support by way of CoreWLAN offered in Mac OS 10.6. Previous + \li Mac OS\unicode{0xAE} + \li This platform has full support by way of CoreWLAN offered in Mac OS 10.6. Previous versions of Mac OS - 10.5 and 10.4 have limited support. \row - \o All other platforms (*nix, Windows Mobile) - \o This backend is the fallback for all platforms supports network interface notifications via active polling only. + \li All other platforms (*nix, Windows Mobile) + \li This backend is the fallback for all platforms supports network interface notifications via active polling only. \endtable */ diff --git a/doc/src/printsupport/printing.qdoc b/doc/src/printsupport/printing.qdoc index 5277d1c547..5447032a2b 100644 --- a/doc/src/printsupport/printing.qdoc +++ b/doc/src/printsupport/printing.qdoc @@ -112,7 +112,7 @@ too small for the higher resolutions of typical printers. \table - \row \o \bold{Printer and Painter Coordinate Systems} + \row \li \b{Printer and Painter Coordinate Systems} The \l{QPrinter::}{paperRect()} and \l{QPrinter::}{pageRect()} functions provide information about the size of the paper used for printing and the @@ -126,7 +126,7 @@ rectangle, and painting operations will be clipped to the bounds of the drawable part of the page. - \o \inlineimage printer-rects.png + \li \inlineimage printer-rects.png \endtable The paint system automatically uses the correct device metrics when painting @@ -164,12 +164,12 @@ functionality can be obtained via a function in the corresponding widget's API. \table - \header \o Widget \o Printing function \o Accepts - \row \o QGraphicsView \o QGraphicsView::render() \o QPainter - \row \o QSvgWidget \o QSvgRenderer::render() \o QPainter - \row \o QTextEdit \o QTextDocument::print() \o QPrinter - \row \o QTextLayout \o QTextLayout::draw() \o QPainter - \row \o QTextLine \o QTextLine::draw() \o QPainter + \header \li Widget \li Printing function \li Accepts + \row \li QGraphicsView \li QGraphicsView::render() \li QPainter + \row \li QSvgWidget \li QSvgRenderer::render() \li QPainter + \row \li QTextEdit \li QTextDocument::print() \li QPrinter + \row \li QTextLayout \li QTextLayout::draw() \li QPainter + \row \li QTextLine \li QTextLine::draw() \li QPainter \endtable QTextEdit requires a QPrinter rather than a QPainter because it uses information diff --git a/doc/src/sql/sql-programming/qsqldatatype-table.qdoc b/doc/src/sql/sql-programming/qsqldatatype-table.qdoc index bc1c8b3c13..a7e03cf28f 100644 --- a/doc/src/sql/sql-programming/qsqldatatype-table.qdoc +++ b/doc/src/sql/sql-programming/qsqldatatype-table.qdoc @@ -48,518 +48,518 @@ \table 90% \header - \o IBM DB2 data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li IBM DB2 data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o SMALLINT - \o 16-bit signed integer - \o typedef qint16 + \li SMALLINT + \li 16-bit signed integer + \li typedef qint16 \row - \o INTEGER - \o 32-bit signed integer - \o typedef qint32 + \li INTEGER + \li 32-bit signed integer + \li typedef qint32 \row - \o BIGINT - \o 64-bit signed integer - \o typedef qint64 + \li BIGINT + \li 64-bit signed integer + \li typedef qint64 \row - \o REAL - \o 32-bit Single-precision floating point - \o By default mapping to QString + \li REAL + \li 32-bit Single-precision floating point + \li By default mapping to QString \row - \o DOUBLE PRECISION - \o 64-bit Double-precision floating point - \o By default mapping to QString + \li DOUBLE PRECISION + \li 64-bit Double-precision floating point + \li By default mapping to QString \row - \o FLOAT - \o 64-bit Double-precision floating point - \o By default mapping to QString + \li FLOAT + \li 64-bit Double-precision floating point + \li By default mapping to QString \row - \o CHAR - \o Fixed-length, null-terminated character string - \o Mapped to QString + \li CHAR + \li Fixed-length, null-terminated character string + \li Mapped to QString \row - \o VARCHAR - \o Null-terminated varying length string - \o Mapped to QString + \li VARCHAR + \li Null-terminated varying length string + \li Mapped to QString \row - \o LONG VARCHAR - \o Not null-terminated varying length character string - \o Mapped to QString + \li LONG VARCHAR + \li Not null-terminated varying length character string + \li Mapped to QString \row - \o BLOB - \o Not null-terminated varying binary string with 4-byte string + \li BLOB + \li Not null-terminated varying binary string with 4-byte string length indicator - \o Mapped to QByteArray + \li Mapped to QByteArray \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o DATE - \o Null-terminated character string of the following format: + \li DATE + \li Null-terminated character string of the following format: yyyy-mm-dd - \o Mapped to QDate + \li Mapped to QDate \row - \o TIME - \o Null-terminated character string of the following format: hh.mm.ss - \o Mapped to QTime + \li TIME + \li Null-terminated character string of the following format: hh.mm.ss + \li Mapped to QTime \row - \o TIMESTAMP - \o Null-terminated character string of the following format: yyyy-mm-dd-hh.mm.ss.nnnnnn - \o Mapped to QDateTime + \li TIMESTAMP + \li Null-terminated character string of the following format: yyyy-mm-dd-hh.mm.ss.nnnnnn + \li Mapped to QDateTime \endtable \section2 Borland InterBase Data Types \table 90% \header - \o Borland InterBase data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li Borland InterBase data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o BOOLEAN - \o Boolean - \o bool + \li BOOLEAN + \li Boolean + \li bool \row - \o TINYINT - \o 8 bit signed integer - \o typedef qint8 + \li TINYINT + \li 8 bit signed integer + \li typedef qint8 \row - \o SMALLINT - \o 16-bit signed integer - \o typedef qint16 + \li SMALLINT + \li 16-bit signed integer + \li typedef qint16 \row - \o INTEGER - \o 32-bit signed integer - \o typedef qint32 + \li INTEGER + \li 32-bit signed integer + \li typedef qint32 \row - \o BIGINT LONG - \o 64-bit signed integer - \o typedef qint64 + \li BIGINT LONG + \li 64-bit signed integer + \li typedef qint64 \row - \o REAL FLOAT - \o 32-bit floating point - \o By default mapping to QString + \li REAL FLOAT + \li 32-bit floating point + \li By default mapping to QString \row - \o FLOAT - \o 64-bit floating point - \o By default mapping to QString + \li FLOAT + \li 64-bit floating point + \li By default mapping to QString \row - \o DOUBLE - \o 64-bit floating point - \o By default mapping to QString + \li DOUBLE + \li 64-bit floating point + \li By default mapping to QString \row - \o DOUBLE PRECISION - \o 64-bit Double-precision floating point - \o By default mapping to QString + \li DOUBLE PRECISION + \li 64-bit Double-precision floating point + \li By default mapping to QString \row - \o VARCHAR STRING - \o Character string, Unicode - \o Mapped to QString + \li VARCHAR STRING + \li Character string, Unicode + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o DATE - \o Displays date. Format: 'yyyy-mm-dd' - \o Mapped to QDate + \li DATE + \li Displays date. Format: 'yyyy-mm-dd' + \li Mapped to QDate \row - \o TIME - \o Displays time. Format is 'hh:mm:ss' in 24-hour format - \o Mapped to QTime + \li TIME + \li Displays time. Format is 'hh:mm:ss' in 24-hour format + \li Mapped to QTime \row - \o TIMESTAMP - \o Displays a timestamp. Format is 'yyyy-mm-dd hh:mm:ss' - \o Mapped to QDateTime + \li TIMESTAMP + \li Displays a timestamp. Format is 'yyyy-mm-dd hh:mm:ss' + \li Mapped to QDateTime \endtable \section2 MySQL Data Types \table 90% \header - \o MySQL data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li MySQL data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o TINYINT - \o 8 bit signed integer - \o typedef qint8 + \li TINYINT + \li 8 bit signed integer + \li typedef qint8 \row - \o TINYINT UNSIGNED - \o 8 bit unsigned integer - \o typedef quint8 + \li TINYINT UNSIGNED + \li 8 bit unsigned integer + \li typedef quint8 \row - \o SMALLINT - \o 16-bit signed integer - \o typedef qint16 + \li SMALLINT + \li 16-bit signed integer + \li typedef qint16 \row - \o SMALLINT UNSIGNED - \o 16-bit unsigned integer - \o typedef quint16 + \li SMALLINT UNSIGNED + \li 16-bit unsigned integer + \li typedef quint16 \row - \o INT - \o 32-bit signed integer - \o typedef qint32 + \li INT + \li 32-bit signed integer + \li typedef qint32 \row - \o INT UNSIGNED - \o 32-bit unsigned integer - \o typedef quint32 + \li INT UNSIGNED + \li 32-bit unsigned integer + \li typedef quint32 \row - \o BIGINT - \o 64-bit signed integer - \o typedef qint64 + \li BIGINT + \li 64-bit signed integer + \li typedef qint64 \row - \o FLOAT - \o 32-bit Floating Point - \o By default mapping to QString + \li FLOAT + \li 32-bit Floating Point + \li By default mapping to QString \row - \o DOUBLE - \o 64-bit Floating Point - \o By default mapping to QString + \li DOUBLE + \li 64-bit Floating Point + \li By default mapping to QString \row - \o CHAR - \o Character string - \o Mapped to QString + \li CHAR + \li Character string + \li Mapped to QString \row - \o VARCHAR - \o Character string - \o Mapped to QString + \li VARCHAR + \li Character string + \li Mapped to QString \row - \o TINYTEXT - \o Character string - \o Mapped to QString + \li TINYTEXT + \li Character string + \li Mapped to QString \row - \o TEXT - \o Character string - \o Mapped to QString + \li TEXT + \li Character string + \li Mapped to QString \row - \o MEDIUMTEXT - \o Character string - \o Mapped to QString + \li MEDIUMTEXT + \li Character string + \li Mapped to QString \row - \o LONGTEXT - \o Character string - \o Mapped to QString + \li LONGTEXT + \li Character string + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o all BLOB types - \o BLOB - \o Mapped to QByteArray + \li all BLOB types + \li BLOB + \li Mapped to QByteArray \row - \o DATE - \o Date without Time - \o Mapped to QDate + \li DATE + \li Date without Time + \li Mapped to QDate \row - \o DATETIME - \o Date and Time - \o Mapped to QDateTime + \li DATETIME + \li Date and Time + \li Mapped to QDateTime \row - \o TIMESTAMP - \o Date and Time - \o Mapped to QDateTime + \li TIMESTAMP + \li Date and Time + \li Mapped to QDateTime \row - \o TIME - \o Time - \o Mapped to QTime + \li TIME + \li Time + \li Mapped to QTime \row - \o YEAR - \o Year (int) - \o Mapped to QDateTime + \li YEAR + \li Year (int) + \li Mapped to QDateTime \row - \o ENUM - \o Enumeration of Value Set - \o Mapped to QString + \li ENUM + \li Enumeration of Value Set + \li Mapped to QString \endtable \section2 Oracle Call Interface Data Types \table 90% \header - \o Oracle Call Interface data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li Oracle Call Interface data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o NUMBER - \o FLOAT, DOUBLE, PRECISIONc REAL - \o By default mapping to QString + \li NUMBER + \li FLOAT, DOUBLE, PRECISIONc REAL + \li By default mapping to QString \row - \o NUMBER(38) - \o INTEGER INT SMALLINT - \o typedef qint8/16/32/64 + \li NUMBER(38) + \li INTEGER INT SMALLINT + \li typedef qint8/16/32/64 \row - \o NUMBER(p,s) - \o NUMERIC(p,s) DECIMAL(p,s)a - \o By default mapping to QString + \li NUMBER(p,s) + \li NUMERIC(p,s) DECIMAL(p,s)a + \li By default mapping to QString \row - \o NVARCHAR2(n) - \o Character string (NATIONAL CHARACTER VARYING(n) NATIONAL + \li NVARCHAR2(n) + \li Character string (NATIONAL CHARACTER VARYING(n) NATIONAL CHAR VARYING(n) NCHAR VARYING(n)) - \o Mapped to QString + \li Mapped to QString \row - \o NCHAR(n) - \o Character string (NATIONAL CHARACTER(n) NATIONAL CHAR(n) + \li NCHAR(n) + \li Character string (NATIONAL CHARACTER(n) NATIONAL CHAR(n) NCHAR(n)) - \o Mapped to QString + \li Mapped to QString \row - \o CHAR(n) - \o Character string (CHARACTER(n) CHAR(n)) - \o Mapped to QString + \li CHAR(n) + \li Character string (CHARACTER(n) CHAR(n)) + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o BLOB - \o A binary large object - \o Mapped to QByteArray + \li BLOB + \li A binary large object + \li Mapped to QByteArray \row - \o TIMESTAMP - \o Year, month, and day values of date, as well as hour, minute, + \li TIMESTAMP + \li Year, month, and day values of date, as well as hour, minute, and second values of time - \o Mapped to QDateTime + \li Mapped to QDateTime \endtable \section2 ODBC Data Types \table 90% \header - \o ODBC data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li ODBC data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o BIT - \o Boolean - \o BOOL + \li BIT + \li Boolean + \li BOOL \row - \o TINYINT - \o 8 bit integer - \o typedef qint8 + \li TINYINT + \li 8 bit integer + \li typedef qint8 \row - \o SMALLINT - \o 16-bit signed integer - \o typedef qint16 + \li SMALLINT + \li 16-bit signed integer + \li typedef qint16 \row - \o INTEGER - \o 32-bit signed integer - \o typedef qint32 + \li INTEGER + \li 32-bit signed integer + \li typedef qint32 \row - \o BIGINT - \o 64-bit signed integer - \o typedef qint64 + \li BIGINT + \li 64-bit signed integer + \li typedef qint64 \row - \o REAL - \o 32-bit Single-precision floating point - \o By default mapping to QString + \li REAL + \li 32-bit Single-precision floating point + \li By default mapping to QString \row - \o FLOAT - \o 64-bit Double floating point - \o By default mapping to QString + \li FLOAT + \li 64-bit Double floating point + \li By default mapping to QString \row - \o DOUBLE - \o 64-bit Double floating point - \o By default mapping to QString + \li DOUBLE + \li 64-bit Double floating point + \li By default mapping to QString \row - \o CHAR - \o Character string - \o Mapped to QString + \li CHAR + \li Character string + \li Mapped to QString \row - \o VARCHAR - \o Character string - \o Mapped to QString + \li VARCHAR + \li Character string + \li Mapped to QString \row - \o LONGVARCHAR - \o Character string - \o Mapped to QString + \li LONGVARCHAR + \li Character string + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o DATE - \o Character string - \o Mapped to QDate + \li DATE + \li Character string + \li Mapped to QDate \row - \o TIME - \o Character Time, Character string - \o Mapped to QTime + \li TIME + \li Character Time, Character string + \li Mapped to QTime \row - \o TIMESTAMP - \o Character Time, Character string - \o Mapped to QDateTime + \li TIMESTAMP + \li Character Time, Character string + \li Mapped to QDateTime \endtable \section2 PostgreSQL Data Types \table 90% \header - \o PostgreSQL data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li PostgreSQL data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o BOOLEAN - \o Boolean - \o bool + \li BOOLEAN + \li Boolean + \li bool \row - \o SMALLINT - \o 16-bit signed integer - \o typedef qint16 + \li SMALLINT + \li 16-bit signed integer + \li typedef qint16 \row - \o INTEGER - \o 32-bit signed integer - \o typedef qint32 + \li INTEGER + \li 32-bit signed integer + \li typedef qint32 \row - \o BIGINT - \o 64-bit signed integer - \o typedef qint64 + \li BIGINT + \li 64-bit signed integer + \li typedef qint64 \row - \o REAL - \o 32-bit variable-precision floating point - \o By default mapping to QString + \li REAL + \li 32-bit variable-precision floating point + \li By default mapping to QString \row - \o DOUBLE PRECISION - \o 64-bit variable-precision floating point - \o By default mapping to QString + \li DOUBLE PRECISION + \li 64-bit variable-precision floating point + \li By default mapping to QString \row - \o DECIMAL VARIABLE - \o user-specified precision, exact - \o Mapped to QString + \li DECIMAL VARIABLE + \li user-specified precision, exact + \li Mapped to QString \row - \o NUMERIC VARIABLE - \o user-specified precision, exact - \o Mapped to QString + \li NUMERIC VARIABLE + \li user-specified precision, exact + \li Mapped to QString \row - \o VARCHAR - \o variable-length character string - \o Mapped to QString + \li VARCHAR + \li variable-length character string + \li Mapped to QString \row - \o CHARACTER - \o Character string of fixed-length - \o Mapped to QString + \li CHARACTER + \li Character string of fixed-length + \li Mapped to QString \row - \o TEXT - \o Character string of variable-length - \o Mapped to QString + \li TEXT + \li Character string of variable-length + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o TIMESTAMP - \o 8 bytes, both date and time - \o Mapped to QDateTime + \li TIMESTAMP + \li 8 bytes, both date and time + \li Mapped to QDateTime \row - \o TIMESTAMP - \o 8 bytes, both date and time, with time zone - \o Mapped to QDateTime + \li TIMESTAMP + \li 8 bytes, both date and time, with time zone + \li Mapped to QDateTime \row - \o DATE - \o 4 bytes, dates only - \o Mapped to QDate + \li DATE + \li 4 bytes, dates only + \li Mapped to QDate \row - \o TIME - \o 8 bytes, times of day only 00:00:00.00 - 23:59:59.99 - \o Mapped to QTime + \li TIME + \li 8 bytes, times of day only 00:00:00.00 - 23:59:59.99 + \li Mapped to QTime \row - \o TIME - \o 12 bytes times of day only, with time zone 00:00:00.00+12 - \o Mapped to QDateTime + \li TIME + \li 12 bytes times of day only, with time zone 00:00:00.00+12 + \li Mapped to QDateTime \endtable \section2 QSQLITE SQLite version 3 Data Types \table 90% \header - \o QSQLITE SQLite version 3 data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li QSQLITE SQLite version 3 data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o NULL - \o NULL value. - \o NULL + \li NULL + \li NULL value. + \li NULL \row - \o INTEGER - \o Signed integer, stored in 8, 16, 24, 32, 48, or 64-bits + \li INTEGER + \li Signed integer, stored in 8, 16, 24, 32, 48, or 64-bits depending on the magnitude of the value. - \o typedef qint8/16/32/64 + \li typedef qint8/16/32/64 \row - \o REAL - \o 64-bit floating point value. - \o By default mapping to QString + \li REAL + \li 64-bit floating point value. + \li By default mapping to QString \row - \o TEXT - \o Character string (UTF-8, UTF-16BE or UTF-16-LE). - \o Mapped to QString + \li TEXT + \li Character string (UTF-8, UTF-16BE or UTF-16-LE). + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o BLOB - \o The value is a BLOB of data, stored exactly as it was input. - \o Mapped to QByteArray + \li BLOB + \li The value is a BLOB of data, stored exactly as it was input. + \li Mapped to QByteArray \endtable \section2 Sybase Adaptive Server Data Types \table 90% \header - \o Sybase Adaptive Server data type - \o SQL type description - \o Recommended input (C++ or Qt data type) + \li Sybase Adaptive Server data type + \li SQL type description + \li Recommended input (C++ or Qt data type) \row - \o BINARY - \o Describes a fixed-length binary value up to 255 bytes in size. - \o Mapped to QByteArray + \li BINARY + \li Describes a fixed-length binary value up to 255 bytes in size. + \li Mapped to QByteArray \row - \o CHAR - \o Character String - \o Mapped to QString + \li CHAR + \li Character String + \li Mapped to QString \row - \o DATETIME - \o Date and time. Range: 1753-01-01 00:00:00 through 9999-12-31 23:59:59. - \o Mapped to QDateTime + \li DATETIME + \li Date and time. Range: 1753-01-01 00:00:00 through 9999-12-31 23:59:59. + \li Mapped to QDateTime \row - \o NCHAR - \o Character String of fixed length - \o Mapped to QString + \li NCHAR + \li Character String of fixed length + \li Mapped to QString \row - \o NVARACHAR - \o Character String of variable length - \o Mapped to QString + \li NVARACHAR + \li Character String of variable length + \li Mapped to QString \row - \o VARCHAR - \o Character String of fixed length - \o Mapped to QString + \li VARCHAR + \li Character String of fixed length + \li Mapped to QString \row - \o CLOB - \o Character large string object - \o Mapped to QString + \li CLOB + \li Character large string object + \li Mapped to QString \row - \o TIMESTAMP - \o A unique number within a database - \o Mapped to QString + \li TIMESTAMP + \li A unique number within a database + \li Mapped to QString \row - \o SMALLDATETIME - \o Date and time. Range: 1900-01-01 00:00 through 2079-12-31 23:59 - \o Mapped to QDateTime + \li SMALLDATETIME + \li Date and time. Range: 1900-01-01 00:00 through 2079-12-31 23:59 + \li Mapped to QDateTime \row - \o UNICHAR - \o Character String of fixed length.(Unicode) - \o Mapped to QString + \li UNICHAR + \li Character String of fixed length.(Unicode) + \li Mapped to QString \row - \o UNIVARCHAR - \o Character String of variable length.(Unicode) - \o Mapped to QString + \li UNIVARCHAR + \li Character String of variable length.(Unicode) + \li Mapped to QString \row - \o VARBINARY - \o Describes a variable-length binary value up to 255 bytes in size - \o Mapped to QByteArray + \li VARBINARY + \li Describes a variable-length binary value up to 255 bytes in size + \li Mapped to QByteArray \endtable \section2 SQLite Version 2 diff --git a/doc/src/sql/sql-programming/sql-driver.qdoc b/doc/src/sql/sql-programming/sql-driver.qdoc index 667b9eba54..eec61abd15 100644 --- a/doc/src/sql/sql-programming/sql-driver.qdoc +++ b/doc/src/sql/sql-programming/sql-driver.qdoc @@ -49,18 +49,18 @@ are provided with Open Source Versions of Qt. \table - \header \o Driver name \o DBMS - \row \o \link #QDB2 QDB2\endlink \o IBM DB2 (version 7.1 and above) - \row \o \link #QIBASE QIBASE\endlink \o Borland InterBase - \row \o \link #QMYSQL QMYSQL\endlink \o MySQL - \row \o \link #QOCI QOCI\endlink \o Oracle Call Interface Driver - \row \o \link #QODBC QODBC\endlink - \o Open Database Connectivity (ODBC) - Microsoft SQL Server and other + \header \li Driver name \li DBMS + \row \li \link #QDB2 QDB2\endlink \li IBM DB2 (version 7.1 and above) + \row \li \link #QIBASE QIBASE\endlink \li Borland InterBase + \row \li \link #QMYSQL QMYSQL\endlink \li MySQL + \row \li \link #QOCI QOCI\endlink \li Oracle Call Interface Driver + \row \li \link #QODBC QODBC\endlink + \li Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases - \row \o \link #QPSQL QPSQL\endlink \o PostgreSQL (versions 7.3 and above) - \row \o \link #QSQLITE2 QSQLITE2\endlink \o SQLite version 2 - \row \o \link #QSQLITE QSQLITE\endlink \o SQLite version 3 - \row \o \link #QTDS QTDS\endlink \o Sybase Adaptive Server \note obsolete from Qt 4.7 + \row \li \link #QPSQL QPSQL\endlink \li PostgreSQL (versions 7.3 and above) + \row \li \link #QSQLITE2 QSQLITE2\endlink \li SQLite version 2 + \row \li \link #QSQLITE QSQLITE\endlink \li SQLite version 3 + \row \li \link #QTDS QTDS\endlink \li Sybase Adaptive Server \note obsolete from Qt 4.7 \endtable SQLite is the in-process database system with the best test coverage @@ -69,7 +69,7 @@ Linux. The completeness of the support for other systems depends on the availability and quality of client libraries. - \bold{Note:} To build a driver plugin you need to have the appropriate + \b{Note:} To build a driver plugin you need to have the appropriate client library for your Database Management System (DBMS). This provides access to the API exposed by the DBMS, and is typically shipped with it. Most installation programs also allow you to install "development @@ -123,7 +123,7 @@ \snippet doc/src/snippets/code/doc_src_sql-driver.cpp 2 - \bold{Note:} \c{@outval1} and \c{@outval2} are variables local to the current + \b{Note:} \c{@outval1} and \c{@outval2} are variables local to the current connection and will not be affected by queries sent from another host or connection. @@ -185,59 +185,59 @@ \list - \o Download the following components: + \li Download the following components: \list - \o \c{MinGW-5.1.6.exe} - \o \c{mingw-utils-0.3.tar.gz} - \o Qt sources, e.g. \c{qt-everywhere-opensource-src-4.6.2.zip} - \o \c{mysql-5.1.35-win32.msi} + \li \c{MinGW-5.1.6.exe} + \li \c{mingw-utils-0.3.tar.gz} + \li Qt sources, e.g. \c{qt-everywhere-opensource-src-4.6.2.zip} + \li \c{mysql-5.1.35-win32.msi} \endlist - \o Install \c{MinGW-5.1.6.exe} in, e.g. \c{C:\MinGW}. + \li Install \c{MinGW-5.1.6.exe} in, e.g. \c{C:\MinGW}. - \o Extract \c{mingw-utils-0.3.tar.gz} into, e.g. \c{C:\MinGW}. + \li Extract \c{mingw-utils-0.3.tar.gz} into, e.g. \c{C:\MinGW}. - \o Add the path for \c{MinGW-5.1.6.exe} to your \c{PATH} variable, + \li Add the path for \c{MinGW-5.1.6.exe} to your \c{PATH} variable, e.g. \c{C:\MinGW\bin;} - \o Extract the Qt sources, (\c{qt-everywhere-opensource-src-4.6.2.zip}), + \li Extract the Qt sources, (\c{qt-everywhere-opensource-src-4.6.2.zip}), into, e.g. \c{C:\Qt}. - \o Add the path for the eventual Qt binary to your \c{PATH} variable, + \li Add the path for the eventual Qt binary to your \c{PATH} variable, e.g. \c{C:\Qt\4.6.2\bin;}. - \o Install MySQL (\c{mysql-5.1.35-win32.msi}), customizing the + \li Install MySQL (\c{mysql-5.1.35-win32.msi}), customizing the components. Select only the headers and libraries. Install in, e.g. \c{C:\MySQL\MySQL51}. - \o Open the DOS prompt, go to \c{C:\MySQL\MySQL51\lib\opt}, and run + \li Open the DOS prompt, go to \c{C:\MySQL\MySQL51\lib\opt}, and run the following commands: \list - \o \c{reimp -d libmysql.lib} - \o \c{dlltool -k -d libmysql.def -l libmysql.a} + \li \c{reimp -d libmysql.lib} + \li \c{dlltool -k -d libmysql.def -l libmysql.a} \endlist - \o Open the DOS prompt, go to \c{C:\Qt\4.6.2} and run the following commands: + \li Open the DOS prompt, go to \c{C:\Qt\4.6.2} and run the following commands: \list - \o \c{configure.exe -debug-and-release -platform win32-g++ -qt-sql-mysql + \li \c{configure.exe -debug-and-release -platform win32-g++ -qt-sql-mysql -l mysql -I C:\MySQL\MySQL51\include -L C:\MySQL\MySQL51\lib\opt} - \o \c{mingw32-make sub-src} + \li \c{mingw32-make sub-src} \endlist This step takes a long time. - \o Open the DOS prompt, go to + \li Open the DOS prompt, go to \c{C:\Qt\4.6.2\src\plugins\sqldrivers\mysql} and run the following command: \list - \o \c{qmake "INCLUDEPATH+=C:\MySQL\MySQL51\include" "LIBS+=-L. mysql" mysql.pro} + \li \c{qmake "INCLUDEPATH+=C:\MySQL\MySQL51\include" "LIBS+=-L. mysql" mysql.pro} \endlist - \o Now the following libraries are ready in \c{C:\Qt\4.6.2\plugins\sqldrivers}. + \li Now the following libraries are ready in \c{C:\Qt\4.6.2\plugins\sqldrivers}. \list - \o \c{libqsqlmysql4.a} - \o \c{libqsqlmysqld4.a} - \o \c{qsqlmysql4.dll} - \o \c{qsqlmysqld4.dll} + \li \c{libqsqlmysql4.a} + \li \c{libqsqlmysqld4.a} + \li \c{qsqlmysql4.dll} + \li \c{qsqlmysqld4.dll} \endlist To use the SDK and QtCreator directly, copy these libraries to your \c{C:\Qt\...\qt\plugins\sqldrivers\}, and copy @@ -287,8 +287,8 @@ Oracle library files required to build the driver: \list - \i \c libclntsh.so (all versions) - \i \c libwtc9.so (only Oracle 9) + \li \c libclntsh.so (all versions) + \li \c libwtc9.so (only Oracle 9) \endlist Tell \c qmake where to find the Oracle header files and shared @@ -301,7 +301,7 @@ Instant Client Package SDK (you need to adjust the version number accordingly): \snippet doc/src/snippets/code/doc_src_sql-driver.qdoc 7 - \bold{Note:} If you are using the Oracle Instant Client package, + \b{Note:} If you are using the Oracle Instant Client package, you will need to set LD_LIBRARY_PATH when building the OCI SQL plugin and when running an application that uses the OCI SQL plugin. You can avoid this requirement by setting and RPATH and listing all of the @@ -331,7 +331,7 @@ \snippet doc/src/snippets/code/doc_src_sql-driver.qdoc 9 - \bold{Note:} This database plugin is not supported for Windows CE. + \b{Note:} This database plugin is not supported for Windows CE. \target QODBC \section2 QODBC for Open Database Connectivity (ODBC) @@ -345,7 +345,7 @@ driver manager that is installed on your system. The QODBC plugin then allows you to use these data sources in your Qt applications. - \bold{Note:} You should use native drivers in preference to the ODBC + \b{Note:} You should use native drivers in preference to the ODBC driver where they are available. ODBC support can be used as a fallback for compliant databases if no native drivers are available. @@ -396,7 +396,7 @@ \snippet doc/src/snippets/code/doc_src_sql-driver.cpp 10 - \bold{Note:} The value returned by the stored procedure's return statement + \b{Note:} The value returned by the stored procedure's return statement is discarded. \section3 ODBC Unicode Support @@ -435,7 +435,7 @@ If you are not using a Microsoft compiler, replace \c nmake with \c make in the line above. - \bold{Note:} This database plugin is not officially supported for Windows CE. + \b{Note:} This database plugin is not officially supported for Windows CE. \target QPSQL \section2 QPSQL for PostgreSQL (Version 7.3 and Above) @@ -496,7 +496,7 @@ Users of MinGW may wish to consult the following online document: \l{PostgreSQL MinGW/Native Windows}. - \bold{Note:} This database plugin is not supported for Windows CE. + \b{Note:} This database plugin is not supported for Windows CE. \target QTDS \section2 QTDS for Sybase Adaptive Server @@ -515,11 +515,11 @@ Under Unix, two libraries are available which support the TDS protocol: \list - \i FreeTDS, a free implementation of the TDS protocol + \li FreeTDS, a free implementation of the TDS protocol (\l{http://www.freetds.org}). Note that FreeTDS is not yet stable, so some functionality may not work as expected. - \i Sybase Open Client, available from \l{http://www.sybase.com}. + \li Sybase Open Client, available from \l{http://www.sybase.com}. Note for Linux users: Get the Open Client RPM from \l{http://linux.sybase.com}. \endlist @@ -545,7 +545,7 @@ are not using a Microsoft compiler, replace \c nmake with \c make in the line above. - \bold{Note:} This database plugin is not supported for Windows CE. + \b{Note:} This database plugin is not supported for Windows CE. \target QDB2 \section2 QDB2 for IBM DB2 (Version 7.1 and Above) @@ -582,7 +582,7 @@ If you are not using a Microsoft compiler, replace \c nmake with \c make in the line above. - \bold{Note:} This database plugin is not supported for Windows CE. + \b{Note:} This database plugin is not supported for Windows CE. \target QSQLITE2 \section2 QSQLITE2 for SQLite Version 2 @@ -745,7 +745,7 @@ Note that \c{C:\interbase\bin} must be in the \c PATH. - \bold{Note:} This database plugin is not supported for Windows CE. + \b{Note:} This database plugin is not supported for Windows CE. \target troubleshooting \section1 Troubleshooting @@ -763,16 +763,16 @@ make sure that the following requirements are met: \list - \i Ensure that you are using a shared Qt library; you cannot use the + \li Ensure that you are using a shared Qt library; you cannot use the plugins with a static build. - \i Ensure that the plugin is in the correct directory. You can use + \li Ensure that the plugin is in the correct directory. You can use QApplication::libraryPaths() to determine where Qt looks for plugins. - \i Ensure that the client libraries of the DBMS are available on the + \li Ensure that the client libraries of the DBMS are available on the system. On Unix, run the command \c{ldd} and pass the name of the plugin as parameter, for example \c{ldd libqsqlmysql.so}. You will get a warning if any of the client libraries couldn't be found. On Windows, you can use Visual Studio's dependency walker. - \i Compile Qt with \c{QT_DEBUG_COMPONENT} defined to get very verbose + \li Compile Qt with \c{QT_DEBUG_COMPONENT} defined to get very verbose debug output when loading plugins. \endlist diff --git a/doc/src/sql/sql-programming/sql-programming.qdoc b/doc/src/sql/sql-programming/sql-programming.qdoc index 787b48718d..6ebb40b755 100644 --- a/doc/src/sql/sql-programming/sql-programming.qdoc +++ b/doc/src/sql/sql-programming/sql-programming.qdoc @@ -52,18 +52,18 @@ \section1 Topics: \list - \o \l{Database Classes} - \o \l{Connecting to Databases} + \li \l{Database Classes} + \li \l{Connecting to Databases} \list - \o \l{SQL Database Drivers} + \li \l{SQL Database Drivers} \endlist - \o \l{Executing SQL Statements} + \li \l{Executing SQL Statements} \list - \o \l{Data Types for Qt-supported Database Systems} + \li \l{Data Types for Qt-supported Database Systems} \endlist - \o \l{Using the SQL Model Classes} - \o \l{Presenting Data in a Table View} - \o \l{Creating Data-Aware Forms} + \li \l{Using the SQL Model Classes} + \li \l{Presenting Data in a Table View} + \li \l{Creating Data-Aware Forms} \endlist \section1 Database Classes @@ -338,12 +338,12 @@ QSqlTableModel, and QSqlRelationalTableModel. \table - \row \o QSqlQueryModel - \o A read-only model based on an arbitrary SQL query. - \row \o QSqlTableModel - \o A read-write model that works on a single table. - \row \o QSqlRelationalTableModel - \o A QSqlTableModel subclass with foreign key support. + \row \li QSqlQueryModel + \li A read-only model based on an arbitrary SQL query. + \row \li QSqlTableModel + \li A read-write model that works on a single table. + \row \li QSqlRelationalTableModel + \li A QSqlTableModel subclass with foreign key support. \endtable These classes derive from QAbstractTableModel (which in turn @@ -435,8 +435,8 @@ pitfalls, though: \list - \o Without any caching, performance may drop significantly. - \o If you modify a primary key, the record might slip through + \li Without any caching, performance may drop significantly. + \li If you modify a primary key, the record might slip through your fingers while you are trying to populate it. \endlist @@ -450,8 +450,8 @@ that \c authorid is a foreign key. \table - \row \o \inlineimage noforeignkeys.png - \o \inlineimage foreignkeys.png + \row \li \inlineimage noforeignkeys.png + \li \inlineimage foreignkeys.png \endtable The screenshot on the left shows a plain QSqlTableModel in a diff --git a/doc/src/widgets/addressbook-fr.qdoc b/doc/src/widgets/addressbook-fr.qdoc index 4df19d015f..edd53239d0 100644 --- a/doc/src/widgets/addressbook-fr.qdoc +++ b/doc/src/widgets/addressbook-fr.qdoc @@ -40,10 +40,10 @@ par Qt, tel que: \list - \o Les Widgets et leur mise en page à l'aide des layouts - \o Les signaux et slots - \o Les structures de données de collections - \o Les entrées/sorties + \li Les Widgets et leur mise en page à l'aide des layouts + \li Les signaux et slots + \li Les structures de données de collections + \li Les entrées/sorties \endlist Si c'est votre premier contact avec Qt, lisez \l{How to Learn Qt}{Comment apprendre Qt} @@ -54,13 +54,13 @@ Les chapitres du tutoriel: \list 1 - \o \l{tutorials/addressbook-fr/part1}{Conception de l'interface utilisateur} - \o \l{tutorials/addressbook-fr/part2}{Ajouter des adresses} - \o \l{tutorials/addressbook-fr/part3}{Navigation entre les éléments} - \o \l{tutorials/addressbook-fr/part4}{éditer et supprimer des adresses} - \o \l{tutorials/addressbook-fr/part5}{Ajout d'une fonction de recherche} - \o \l{tutorials/addressbook-fr/part6}{Sauvegarde et chargement} - \o \l{tutorials/addressbook-fr/part7}{Fonctionnalités avancées} + \li \l{tutorials/addressbook-fr/part1}{Conception de l'interface utilisateur} + \li \l{tutorials/addressbook-fr/part2}{Ajouter des adresses} + \li \l{tutorials/addressbook-fr/part3}{Navigation entre les éléments} + \li \l{tutorials/addressbook-fr/part4}{éditer et supprimer des adresses} + \li \l{tutorials/addressbook-fr/part5}{Ajout d'une fonction de recherche} + \li \l{tutorials/addressbook-fr/part6}{Sauvegarde et chargement} + \li \l{tutorials/addressbook-fr/part7}{Fonctionnalités avancées} \endlist La petite application que nous développerons ici ne possède pas tous les éléments @@ -99,10 +99,10 @@ Trois fichiers sont nécessaires à l'implémentation de ce carnet d'adresses: \list - \o \c{addressbook.h} - le fichier de définition (header) pour la classe \c AddressBook, - \o \c{addressbook.cpp} - le fichier source, qui comprend l'implémentation de la classe + \li \c{addressbook.h} - le fichier de définition (header) pour la classe \c AddressBook, + \li \c{addressbook.cpp} - le fichier source, qui comprend l'implémentation de la classe \c AddressBook - \o \c{main.cpp} - le fichier qui contient la méthode \c main() , et + \li \c{main.cpp} - le fichier qui contient la méthode \c main() , et une instance de la classe \c AddressBook. \endlist @@ -116,13 +116,13 @@ ou modifier le comportement d'un widget présente les avantages suivants: \list - \o La possibilité d'implémenter des méthodes virtuelles et des méthodes + \li La possibilité d'implémenter des méthodes virtuelles et des méthodes virtuelles pures pour obtenir exactement ce que l'on souhaite, avec la possibilité d'utiliser l'implémentation de la classe mère si besoin est. - \o Cela permet l'encapsulation partielle de l'interface utilisateur dans une classe, + \li Cela permet l'encapsulation partielle de l'interface utilisateur dans une classe, afin que les autres parties de l'application n'aient pas à se soucier de chacun des widgets qui forment l'interface utilisateur. - \o La classe fille peut être utilisée pour créer de nombreux widgets personnalisés + \li La classe fille peut être utilisée pour créer de nombreux widgets personnalisés dans une même application ou bibliothèque, et le code de la classe fille peut être réutilisé dans d'autres projets \endlist @@ -343,7 +343,7 @@ La méthode \c submitContact() peut être divisée en trois parties: \list 1 - \o Nous extrayons les détails du contact depuis \c nameLine et \c addressText + \li Nous extrayons les détails du contact depuis \c nameLine et \c addressText et les stockons dans des objets QString. Nous les validons pour s'assurer que l'utilisateur n'a pas cliqué sur "Add" avec des champs de saisie vides; sinon un message est affiché avec QMessageBox pour rappeller à @@ -351,7 +351,7 @@ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1 - \o Ensuite, nous vérifions si le contact existe déjà. Si aucun contacts + \li Ensuite, nous vérifions si le contact existe déjà. Si aucun contacts existant n'entre en conflit avec le nouveau, nous l'ajoutons à \c contacts et nous affichons un QMessageBox pour informer l'utilisateur que le contact a été ajouté. @@ -363,7 +363,7 @@ Notre objet \c contacts est basé sur des paires clé-valeur formés par le nom et l'adresse, nous voulons nous assurer que la \e clé est unique. - \o Une fois que les deux vérifications précédentes ont été traitées, + \li Une fois que les deux vérifications précédentes ont été traitées, nous restaurons les boutons à leur état normal à l'aide du code suivant: @@ -482,8 +482,8 @@ sur \c contact dans la méthode \c next(), et ensuite: \list - \o Si l'itérateur n'est pas à la fin de \c contacts, nous l'incrémentons - \o Si l'itérateur est à la fin de \c contacts, nous changeons sa position + \li Si l'itérateur n'est pas à la fin de \c contacts, nous l'incrémentons + \li Si l'itérateur est à la fin de \c contacts, nous changeons sa position jusqu'au début de \c contacts. Cela donne l'illusion que notre QMap fonctionne comme une liste circulaire. \endlist @@ -497,11 +497,11 @@ itérateur sur \c contacts et ensuite: \list - \o Si l'itérateur est à la fin de \c contacts, on réinitialise + \li Si l'itérateur est à la fin de \c contacts, on réinitialise l'affichage et on retourne. - \o Si l'itérateur est au début de \c contacts, on change sa + \li Si l'itérateur est au début de \c contacts, on change sa position jusqu'à la fin - \o Ensuite, on décrémente l'itérateur + \li Ensuite, on décrémente l'itérateur \endlist \snippet tutorials/addressbook/part3/addressbook.cpp previous() function @@ -538,9 +538,9 @@ Dans ce chapitre, on définit l'énumération \c Mode avec trois valeurs possibles. \list - \o \c{NavigationMode}, - \o \c{AddingMode}, et - \o \c{EditingMode}. + \li \c{NavigationMode}, + \li \c{AddingMode}, et + \li \c{EditingMode}. \endlist \section1 Définition de la classe AddressBook diff --git a/doc/src/widgets/addressbook.qdoc b/doc/src/widgets/addressbook.qdoc index 96c96df177..27bdb0fac4 100644 --- a/doc/src/widgets/addressbook.qdoc +++ b/doc/src/widgets/addressbook.qdoc @@ -47,10 +47,10 @@ components of Qt, including: \list - \o Widgets and layout managers - \o Container classes - \o Signals and slots - \o Input and output devices + \li Widgets and layout managers + \li Container classes + \li Signals and slots + \li Input and output devices \endlist If you are new to Qt, we recommend reading \l{How to Learn Qt} first. @@ -58,13 +58,13 @@ Tutorial contents: \list 1 - \o \l{tutorials/addressbook/part1}{Designing the User Interface} - \o \l{tutorials/addressbook/part2}{Adding Addresses} - \o \l{tutorials/addressbook/part3}{Navigating between Entries} - \o \l{tutorials/addressbook/part4}{Editing and Removing Addresses} - \o \l{tutorials/addressbook/part5}{Adding a Find Function} - \o \l{tutorials/addressbook/part6}{Loading and Saving} - \o \l{tutorials/addressbook/part7}{Additional Features} + \li \l{tutorials/addressbook/part1}{Designing the User Interface} + \li \l{tutorials/addressbook/part2}{Adding Addresses} + \li \l{tutorials/addressbook/part3}{Navigating between Entries} + \li \l{tutorials/addressbook/part4}{Editing and Removing Addresses} + \li \l{tutorials/addressbook/part5}{Adding a Find Function} + \li \l{tutorials/addressbook/part6}{Loading and Saving} + \li \l{tutorials/addressbook/part7}{Additional Features} \endlist The tutorial source code is located in \c{examples/tutorials/addressbook}. @@ -105,11 +105,11 @@ There are three files used to implement this address book: \list - \o \c{addressbook.h} - the definition file for the \c AddressBook + \li \c{addressbook.h} - the definition file for the \c AddressBook class, - \o \c{addressbook.cpp} - the implementation file for the + \li \c{addressbook.cpp} - the implementation file for the \c AddressBook class, and - \o \c{main.cpp} - the file containing a \c main() function, with + \li \c{main.cpp} - the file containing a \c main() function, with an instance of \c AddressBook. \endlist @@ -121,13 +121,13 @@ extend or change the behavior of a widget has the following advantages: \list - \o We can write implementations of virtual or pure virtual functions to + \li We can write implementations of virtual or pure virtual functions to obtain exactly what we need, falling back on the base class's implementation when necessary. - \o It allows us to encapsulate parts of the user interface within a class, + \li It allows us to encapsulate parts of the user interface within a class, so that the other parts of the application don't need to know about the individual widgets in the user interface. - \o The subclass can be used to create multiple custom widgets in the same + \li The subclass can be used to create multiple custom widgets in the same application or library, and the code for the subclass can be reused in other projects. \endlist @@ -340,14 +340,14 @@ The \c submitContact() function can be divided into three parts: \list 1 - \o We extract the contact's details from \c nameLine and \c addressText + \li We extract the contact's details from \c nameLine and \c addressText and store them in QString objects. We also validate to make sure that the user did not click \gui Submit with empty input fields; otherwise, a QMessageBox is displayed to remind the user for a name and address. \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1 - \o We then proceed to check if the contact already exists. If it does not + \li We then proceed to check if the contact already exists. If it does not exist, we add the contact to \c contacts and we display a QMessageBox to inform the user that the contact has been added. @@ -358,7 +358,7 @@ Our \c contacts object is based on key-value pairs of name and address, hence, we want to ensure that \e key is unique. - \o Once we have handled both cases mentioned above, we restore the push + \li Once we have handled both cases mentioned above, we restore the push buttons to their normal state with the following code: \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3 @@ -471,9 +471,9 @@ for \c contacts and then: \list - \o If the iterator is not at the end of \c contacts, we increment it + \li If the iterator is not at the end of \c contacts, we increment it by one. - \o If the iterator is at the end of \c contacts, we move it to the + \li If the iterator is at the end of \c contacts, we move it to the beginning of \c contacts. This gives us the illusion that our QMap is working like a circularly-linked list. \endlist @@ -487,11 +487,11 @@ \c contacts and then: \list - \o If the iterator is at the end of \c contacts, we clear the + \li If the iterator is at the end of \c contacts, we clear the display and return. - \o If the iterator is at the beginning of \c contacts, we move it to + \li If the iterator is at the beginning of \c contacts, we move it to the end. - \o We then decrement the iterator by one. + \li We then decrement the iterator by one. \endlist \snippet tutorials/addressbook/part3/addressbook.cpp previous() function @@ -524,9 +524,9 @@ Here we define the \c Mode enum with three different values: \list - \o \c{NavigationMode}, - \o \c{AddingMode}, and - \o \c{EditingMode}. + \li \c{NavigationMode}, + \li \c{AddingMode}, and + \li \c{EditingMode}. \endlist \section1 Defining the AddressBook Class diff --git a/doc/src/widgets/modelview.qdoc b/doc/src/widgets/modelview.qdoc index 536b521100..fdd25def31 100644 --- a/doc/src/widgets/modelview.qdoc +++ b/doc/src/widgets/modelview.qdoc @@ -55,16 +55,16 @@ such as: \list - \o The difference between standard and model/view widgets - \o Adapters between forms and models - \o Developing a simple model/view application - \o Predefined models - \o Intermediate topics such as: + \li The difference between standard and model/view widgets + \li Adapters between forms and models + \li Developing a simple model/view application + \li Predefined models + \li Intermediate topics such as: \list - \o Tree views - \o Selection - \o Delegates - \o Debugging with model test + \li Tree views + \li Selection + \li Delegates + \li Debugging with model test \endlist \endlist @@ -91,11 +91,11 @@ \table \row - \o Standard widgets use data that is part of the widget. - \o \image standardwidget.png + \li Standard widgets use data that is part of the widget. + \li \image standardwidget.png \row - \o View classes operate on external data (the model) - \o \image modelview.png + \li View classes operate on external data (the model) + \li \image modelview.png \endtable \section2 1.1 Standard Widgets @@ -133,30 +133,30 @@ \table \header - \o Widget - \o Standard Widget\br + \li Widget + \li Standard Widget\br (an item based convenience class) - \o Model/View View Class\br + \li Model/View View Class\br (for use with external data) \row - \o \inlineimage listview.png - \o \l QListWidget - \o \l QListView + \li \inlineimage listview.png + \li \l QListWidget + \li \l QListView \row - \o \inlineimage tableview.png - \o \l QTableWidget - \o \l QTableView + \li \inlineimage tableview.png + \li \l QTableWidget + \li \l QTableView \row - \o \inlineimage treeview.png - \o \l QTreeWidget - \o \l QTreeView + \li \inlineimage treeview.png + \li \l QTreeWidget + \li \l QTreeView \row - \o \inlineimage columnview.png - \o - \o \l QColumnView shows a tree as a hierarchy of lists + \li \inlineimage columnview.png + \li + \li \l QColumnView shows a tree as a hierarchy of lists \row - \o \inlineimage modelview-combobox.png - \o {2, 1} \l QComboBox can work as both a view class and also + \li \inlineimage modelview-combobox.png + \li {2, 1} \l QComboBox can work as both a view class and also as a traditional widget \endtable @@ -212,8 +212,8 @@ things: \list - \o How many rows and columns should be displayed. - \o What content should be printed into each cell. + \li How many rows and columns should be displayed. + \li What content should be printed into each cell. \endlist The model needs some code to respond to this. @@ -271,33 +271,33 @@ \table \header - \o \l{Qt::ItemDataRole}{enum Qt::ItemDataRole} - \o Meaning - \o Type + \li \l{Qt::ItemDataRole}{enum Qt::ItemDataRole} + \li Meaning + \li Type \row - \o \l{Qt::ItemDataRole}{}Qt::DisplayRole - \o text - \o QString + \li \l{Qt::ItemDataRole}{}Qt::DisplayRole + \li text + \li QString \row - \o \l{Qt::ItemDataRole}{Qt::FontRole} - \o font - \o QFont + \li \l{Qt::ItemDataRole}{Qt::FontRole} + \li font + \li QFont \row - \o \l{Qt::ItemDataRole}{BackgroundRole} - \o brush for the background of the cell - \o QBrush + \li \l{Qt::ItemDataRole}{BackgroundRole} + \li brush for the background of the cell + \li QBrush \row - \o \l{Qt::ItemDataRole}{Qt::TextAlignmentRole} - \o text alignment - \o \l{Qt::AlignmentFlag}{enum Qt::AlignmentFlag} + \li \l{Qt::ItemDataRole}{Qt::TextAlignmentRole} + \li text alignment + \li \l{Qt::AlignmentFlag}{enum Qt::AlignmentFlag} \row - \o {1, 3} \l{Qt::ItemDataRole}{Qt::CheckStateRole} - \o {1, 3} suppresses checkboxes with \l{QVariant}{QVariant()}, + \li {1, 3} \l{Qt::ItemDataRole}{Qt::CheckStateRole} + \li {1, 3} suppresses checkboxes with \l{QVariant}{QVariant()}, sets checkboxes with \l{Qt::CheckState}{Qt::Checked} or \l{Qt::CheckState}{Qt::Unchecked} - \o {1, 3} \l{Qt::ItemDataRole}{enum Qt::ItemDataRole} + \li {1, 3} \l{Qt::ItemDataRole}{enum Qt::ItemDataRole} \endtable Refer to the Qt namespace documentation to learn more about the @@ -490,27 +490,27 @@ \table \row - \o QStringListModel - \o Stores a list of strings + \li QStringListModel + \li Stores a list of strings \row - \o QStandardItemModel - \o Stores arbitrary hierarchical items + \li QStandardItemModel + \li Stores arbitrary hierarchical items \row - \o QFileSystemModel\br + \li QFileSystemModel\br QDirModel - \o Encapsulate the local file system + \li Encapsulate the local file system \row - \o QSqlQueryModel - \o Encapsulate an SQL result set + \li QSqlQueryModel + \li Encapsulate an SQL result set \row - \o QSqlTableModel - \o Encapsulates an SQL table + \li QSqlTableModel + \li Encapsulates an SQL table \row - \o QSqlRelationalTableModel - \o Encapsulates an SQL table with foreign keys + \li QSqlRelationalTableModel + \li Encapsulates an SQL table with foreign keys \row - \o QSortFilterProxyModel - \o Sorts and/or filters another model + \li QSortFilterProxyModel + \li Sorts and/or filters another model \endtable @@ -562,11 +562,11 @@ Other references to delegates in Qt Documentation: \list - \o \l{Spin Box Delegate Example} - \o \l{QAbstractItemDelegate}{QAbstractItemDelegate Class Reference} - \o \l{QSqlRelationalDelegate}{QSqlRelationalDelegate Class Reference} - \o \l{QStyledItemDelegate}{QStyledItemDelegate Class Reference} - \o \l{QItemDelegate}{QItemDelegate Class Reference} + \li \l{Spin Box Delegate Example} + \li \l{QAbstractItemDelegate}{QAbstractItemDelegate Class Reference} + \li \l{QSqlRelationalDelegate}{QSqlRelationalDelegate Class Reference} + \li \l{QStyledItemDelegate}{QStyledItemDelegate Class Reference} + \li \l{QItemDelegate}{QItemDelegate Class Reference} \endlist @@ -599,16 +599,16 @@ Qt but also in several good books. \list 1 - \o \bold{C++ GUI Programming with Qt 4} / Jasmin Blanchette, Mark Summerfield, + \li \b{C++ GUI Programming with Qt 4} / Jasmin Blanchette, Mark Summerfield, \e{Prentice Hall, 2nd edition}, ISBN 0-13-235416-0. Also available in - German: \bold{C++ GUI Programmierung mit Qt 4: Die offizielle Einführung}, + German: \b{C++ GUI Programmierung mit Qt 4: Die offizielle Einführung}, \e{Addison-Wesley}, ISBN 3-827327-29-6 - \o \bold{The Book of Qt4, The Art of Building Qt Applications} / Daniel Molkentin, + \li \b{The Book of Qt4, The Art of Building Qt Applications} / Daniel Molkentin, \e{Open Source Press}, ISBN 1-59327-147-6. - Translated from \bold{Qt 4, Einführung in die Applikationsentwicklung}, + Translated from \b{Qt 4, Einführung in die Applikationsentwicklung}, \e{Open Source Press}, ISBN 3-937514-12-0. - \o \bold{Foundations of Qt Development} / Johan Thelin, \e{Apress}, ISBN 1-59059-831-8. - \o \bold{Advanced Qt Programming} / Mark Summerfield, \e{Prentice Hall}, ISBN 0-321-63590-6. + \li \b{Foundations of Qt Development} / Johan Thelin, \e{Apress}, ISBN 1-59059-831-8. + \li \b{Advanced Qt Programming} / Mark Summerfield, \e{Prentice Hall}, ISBN 0-321-63590-6. This book covers Model/View programming on more than 150 pages. \endlist @@ -621,157 +621,157 @@ \table \header - \o Example name - \o View class used - \o Model used - \o Aspects covered - \o - \row - \o Team Leaders - \o QListview - \o QStringListModel - \o - \o Book 1, Chapter 10, Figure 10.6 - \row - \o Directory Viewer - \o QTreeView - \o QDirModel - \o - \o Book 1, Chapter 10, Figure 10.7 - \row - \o Color Names - \o QListView - \o QSortFilterProxyModel + \li Example name + \li View class used + \li Model used + \li Aspects covered + \li + \row + \li Team Leaders + \li QListview + \li QStringListModel + \li + \li Book 1, Chapter 10, Figure 10.6 + \row + \li Directory Viewer + \li QTreeView + \li QDirModel + \li + \li Book 1, Chapter 10, Figure 10.7 + \row + \li Color Names + \li QListView + \li QSortFilterProxyModel applied to QStringListModel - \o - \o Book 1, Chapter 10, Figure 10.8 + \li + \li Book 1, Chapter 10, Figure 10.8 \row - \o Currencies - \o QTableView - \o custom model based on + \li Currencies + \li QTableView + \li custom model based on QAbstractTableModel - \o Read only - \o Book 1, Chapter 10, Figure 10.10 + \li Read only + \li Book 1, Chapter 10, Figure 10.10 \row - \o Cities - \o QTableView - \o Custom model based on + \li Cities + \li QTableView + \li Custom model based on QAbstractTableModel - \o Read / write - \o Book 1, Chapter 10, Figure 10.12 + \li Read / write + \li Book 1, Chapter 10, Figure 10.12 \row - \o Boolean Parser - \o QTreeView - \o Custom model based on + \li Boolean Parser + \li QTreeView + \li Custom model based on QAbstractItemModel - \o Read only - \o Book 1, Chapter 10, Figure 10.14 + \li Read only + \li Book 1, Chapter 10, Figure 10.14 \row - \o Track Editor - \o {2, 1} QTableWidget - \o Custom delegate providing a custom editor - \o Book 1, Chapter 10, Figure 10.15 + \li Track Editor + \li {2, 1} QTableWidget + \li Custom delegate providing a custom editor + \li Book 1, Chapter 10, Figure 10.15 \row - \o Four directory views - \o QListView + \li Four directory views + \li QListView QTableView QTreeView - \o QDirModel - \o Demonstrates the use of multiple views - \o Book2, Chapter 8.2 + \li QDirModel + \li Demonstrates the use of multiple views + \li Book2, Chapter 8.2 \row - \o Address Book - \o QListView + \li Address Book + \li QListView QTableView QTreeView - \o Custom model based on + \li Custom model based on QAbstractTableModel - \o Read / write - \o Book2, Chapter 8.4 + \li Read / write + \li Book2, Chapter 8.4 \row - \o Address Book with sorting - \o - \o QProxyModel - \o Introducing sort and filter capabilities - \o Book2, Chapter 8.5 + \li Address Book with sorting + \li + \li QProxyModel + \li Introducing sort and filter capabilities + \li Book2, Chapter 8.5 \row - \o Address Book + \li Address Book with checkboxes - \o - \o - \o Introducing checkboxes in model/view - \o Book2, Chapter 8.6 - \row - \o Address Book with transposed grid - \o - \o Custom proxy Model based on QAbstractProxyModel - \o Introducing a custom model - \o Book2, Chapter 8.7 - \row - \o Address Book with drag and drop - \o - \o - \o Introducing drag and drop support - \o Book2, Chapter 8.8 - \row - \o Address Book with custom editor - \o - \o - \o Introducing custom delegates - \o Book2, Chapter 8.9 - \row - \o Views - \o QListView + \li + \li + \li Introducing checkboxes in model/view + \li Book2, Chapter 8.6 + \row + \li Address Book with transposed grid + \li + \li Custom proxy Model based on QAbstractProxyModel + \li Introducing a custom model + \li Book2, Chapter 8.7 + \row + \li Address Book with drag and drop + \li + \li + \li Introducing drag and drop support + \li Book2, Chapter 8.8 + \row + \li Address Book with custom editor + \li + \li + \li Introducing custom delegates + \li Book2, Chapter 8.9 + \row + \li Views + \li QListView QTableView QTreeView - \o QStandardItemModel - \o Read only - \o Book 3, Chapter 5, figure 5-3 - \row - \o Bardelegate - \o QTableView - \o - \o Custom delegate for presentation based on QAbstractItemDelegate - \o Book 3, Chapter 5, figure 5-5 - \row - \o Editdelegate - \o QTableView - \o - \o Custom delegate for editing based on QAbstractItemDelegate - \o Book 3, Chapter 5, figure 5-6 - \row - \o Singleitemview - \o Custom view based on QAbstractItemView - \o - \o Custom view - \o Book 3, + \li QStandardItemModel + \li Read only + \li Book 3, Chapter 5, figure 5-3 + \row + \li Bardelegate + \li QTableView + \li + \li Custom delegate for presentation based on QAbstractItemDelegate + \li Book 3, Chapter 5, figure 5-5 + \row + \li Editdelegate + \li QTableView + \li + \li Custom delegate for editing based on QAbstractItemDelegate + \li Book 3, Chapter 5, figure 5-6 + \row + \li Singleitemview + \li Custom view based on QAbstractItemView + \li + \li Custom view + \li Book 3, Chapter 5, figure 5-7 \row - \o listmodel - \o QTableView - \o Custom Model based on QAbstractTableModel - \o Read only - \o Book 3, Chapter 5, Figure 5-8 - \row - \o treemodel - \o QTreeView - \o Custom Model based on QAbstractItemModel - \o Read only - \o Book 3, Chapter 5, Figure 5-10 - \row - \o edit integers - \o QListView - \o Custom Model based on QAbstractListModel - \o Read / write - \o Book 3, Chapter 5, Listing 5-37, Figure 5-11 - \row - \o sorting - \o QTableView - \o QSortFilterProxyModel applied to QStringListModel - \o Demonstrates sorting - \o Book 3, Chapter 5, Figure 5-12 + \li listmodel + \li QTableView + \li Custom Model based on QAbstractTableModel + \li Read only + \li Book 3, Chapter 5, Figure 5-8 + \row + \li treemodel + \li QTreeView + \li Custom Model based on QAbstractItemModel + \li Read only + \li Book 3, Chapter 5, Figure 5-10 + \row + \li edit integers + \li QListView + \li Custom Model based on QAbstractListModel + \li Read / write + \li Book 3, Chapter 5, Listing 5-37, Figure 5-11 + \row + \li sorting + \li QTableView + \li QSortFilterProxyModel applied to QStringListModel + \li Demonstrates sorting + \li Book 3, Chapter 5, Figure 5-12 \endtable @@ -782,108 +782,108 @@ \table \header - \o Example name - \o View class used - \o Model used - \o Aspects covered - \row - \o Address Book - \o QTableView - \o QAbstractTableModel + \li Example name + \li View class used + \li Model used + \li Aspects covered + \row + \li Address Book + \li QTableView + \li QAbstractTableModel QSortFilterProxyModel - \o Usage of QSortFilterProxyModel to generate different + \li Usage of QSortFilterProxyModel to generate different subsets from one data pool \row - \o Basic Sort/Filter Model - \o QTreeView - \o QStandardItemModel + \li Basic Sort/Filter Model + \li QTreeView + \li QStandardItemModel QSortFilterProxyModel - \o + \li \row - \o Chart - \o Custom view - \o QStandardItemModel - \o Designing custom views that cooperate with selection models + \li Chart + \li Custom view + \li QStandardItemModel + \li Designing custom views that cooperate with selection models \row - \o Color Editor Factory - \o {2, 1} QTableWidget - \o Enhancing the standard delegate with a new custom editor to choose colours + \li Color Editor Factory + \li {2, 1} QTableWidget + \li Enhancing the standard delegate with a new custom editor to choose colours \row - \o Combo Widget Mapper - \o QDataWidgetMapper to map QLineEdit, QTextEdit and QComboBox - \o QStandardItemModel - \o Shows how a QComboBox can serve as a view class + \li Combo Widget Mapper + \li QDataWidgetMapper to map QLineEdit, QTextEdit and QComboBox + \li QStandardItemModel + \li Shows how a QComboBox can serve as a view class \row - \o Custom Sort/Filter Model - \o QTreeView - \o QStandardItemModel + \li Custom Sort/Filter Model + \li QTreeView + \li QStandardItemModel QSortFilterProxyModel - \o Subclass QSortFilterProxyModel for advanced sorting and filtering + \li Subclass QSortFilterProxyModel for advanced sorting and filtering \row - \o Dir View - \o QTreeView - \o QDirModel - \o Very small example to demonstrate how to assign a model to a view + \li Dir View + \li QTreeView + \li QDirModel + \li Very small example to demonstrate how to assign a model to a view \row - \o Editable Tree Model - \o QTreeView - \o Custom tree model - \o Comprehensive example for working with trees, demonstrates + \li Editable Tree Model + \li QTreeView + \li Custom tree model + \li Comprehensive example for working with trees, demonstrates editing cells and tree structure with an underlying custom model \row - \o Fetch More - \o QListView - \o Custom list model - \o Dynamically changing model - \row - \o Frozen Column - \o QTableView - \o QStandardItemModel - \o - \row - \o Interview - \o Multiple - \o Custom item model - \o Multiple views - \row - \o Pixelator - \o QTableView - \o Custom table model - \o Implementation of a custom delegate - \row - \o Puzzle - \o QListView - \o Custom list model - \o Model/view with drag and drop - \row - \o Simple DOM Model - \o QTreeView - \o Custom tree model - \o Read only example for a custom tree model - \row - \o Simple Tree Model - \o QTreeView - \o Custom tree model - \o Read only example for a custom tree model - \row - \o Simple Widget Mapper - \o QDataWidgetMapper to map QLineEdit, QTextEdit and QSpinBox - \o QStandardItemModel - \o Basic QDataWidgetMapper usage - \row - \o Spin Box Delegate - \o QTableView - \o QStandardItemModel - \o Custom delegate that uses a spin box as a cell editor - \row - \o Spreadsheet - \o {2, 1} QTableView - \o Custom delegates - \row - \o Star Delegate - \o {2, 1} QTableWidget - \o Comprehensive custom delegate example. + \li Fetch More + \li QListView + \li Custom list model + \li Dynamically changing model + \row + \li Frozen Column + \li QTableView + \li QStandardItemModel + \li + \row + \li Interview + \li Multiple + \li Custom item model + \li Multiple views + \row + \li Pixelator + \li QTableView + \li Custom table model + \li Implementation of a custom delegate + \row + \li Puzzle + \li QListView + \li Custom list model + \li Model/view with drag and drop + \row + \li Simple DOM Model + \li QTreeView + \li Custom tree model + \li Read only example for a custom tree model + \row + \li Simple Tree Model + \li QTreeView + \li Custom tree model + \li Read only example for a custom tree model + \row + \li Simple Widget Mapper + \li QDataWidgetMapper to map QLineEdit, QTextEdit and QSpinBox + \li QStandardItemModel + \li Basic QDataWidgetMapper usage + \row + \li Spin Box Delegate + \li QTableView + \li QStandardItemModel + \li Custom delegate that uses a spin box as a cell editor + \row + \li Spreadsheet + \li {2, 1} QTableView + \li Custom delegates + \row + \li Star Delegate + \li {2, 1} QTableWidget + \li Comprehensive custom delegate example. \endtable A \l{Model/View Programming}{reference document} for model/view technology diff --git a/doc/src/widgets/widgets-and-layouts/focus.qdoc b/doc/src/widgets/widgets-and-layouts/focus.qdoc index 374d5781ee..60f05948b4 100644 --- a/doc/src/widgets/widgets-and-layouts/focus.qdoc +++ b/doc/src/widgets/widgets-and-layouts/focus.qdoc @@ -51,11 +51,11 @@ \list 1 - \o The user presses \key Tab (or \key Shift+Tab). - \o The user clicks a widget. - \o The user presses a keyboard shortcut. - \o The user uses the mouse wheel. - \o The user moves the focus to a window, and the application must + \li The user presses \key Tab (or \key Shift+Tab). + \li The user clicks a widget. + \li The user presses a keyboard shortcut. + \li The user uses the mouse wheel. + \li The user moves the focus to a window, and the application must determine which widget within the window should get the focus. \endlist @@ -93,14 +93,14 @@ \list 1 - \o If the program can determine whether the field is needed, it can + \li If the program can determine whether the field is needed, it can move focus there when the user finishes entry and presses \gui OK, or when the user presses Enter after finishing the other fields. Alternately, include the field in the tab order but disable it. Enable it if it becomes appropriate in view of what the user has set in the other fields. - \o The label for the field can include a keyboard shortcut that moves + \li The label for the field can include a keyboard shortcut that moves focus to this field. \endlist diff --git a/doc/src/widgets/widgets-and-layouts/gallery-cde.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-cde.qdoc index 313757ebec..a74cab0509 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-cde.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-cde.qdoc @@ -38,11 +38,11 @@ \table 100% \row -\o \image cde-checkbox.png +\li \image cde-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image cde-radiobutton.png +\li \image cde-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. -\o \image cde-pushbutton.png +\li \image cde-pushbutton.png \image cde-toolbutton.png \caption The QPushButton widget provides a command button. \endtable @@ -51,13 +51,13 @@ \table 100% \row -\o \image cde-groupbox.png +\li \image cde-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image cde-tabwidget.png +\li \image cde-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image cde-frame.png +\li \image cde-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image cde-toolbox.png +\li \image cde-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -65,24 +65,24 @@ \table 100% \row -\o \image cde-listview.png +\li \image cde-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image cde-treeview.png +\li \image cde-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image cde-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image cde-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image cde-progressbar.png +\li \image cde-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image cde-label.png +\li \image cde-label.png The QLabel widget provides a text or image display. -\o \image cde-lcdnumber.png +\li \image cde-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -90,43 +90,43 @@ \table 100% \row -\o \image cde-lineedit.png +\li \image cde-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image cde-dateedit.png +\li \image cde-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image cde-timeedit.png +\li \image cde-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image cde-datetimeedit.png +\li \image cde-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image cde-slider.png +\li \image cde-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image cde-combobox.png +\li \image cde-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image cde-spinbox.png +\li \image cde-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image cde-fontcombobox.png +\li \image cde-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image cde-doublespinbox.png +\li \image cde-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image cde-horizontalscrollbar.png +\li \image cde-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image cde-dial.png +\li \image cde-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image cde-textedit.png +\li \image cde-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image cde-calendarwidget.png +\li \image cde-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable diff --git a/doc/src/widgets/widgets-and-layouts/gallery-cleanlooks.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-cleanlooks.qdoc index 74cd4d4d42..bed6d0ca40 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-cleanlooks.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-cleanlooks.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image cleanlooks-pushbutton.png +\li \image cleanlooks-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image cleanlooks-toolbutton.png +\li \image cleanlooks-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image cleanlooks-checkbox.png +\li \image cleanlooks-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image cleanlooks-radiobutton.png +\li \image cleanlooks-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image cleanlooks-groupbox.png +\li \image cleanlooks-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image cleanlooks-tabwidget.png +\li \image cleanlooks-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image cleanlooks-frame.png +\li \image cleanlooks-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image cleanlooks-toolbox.png +\li \image cleanlooks-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image cleanlooks-listview.png +\li \image cleanlooks-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image cleanlooks-treeview.png +\li \image cleanlooks-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image cleanlooks-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image cleanlooks-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image cleanlooks-progressbar.png +\li \image cleanlooks-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image cleanlooks-label.png +\li \image cleanlooks-label.png The QLabel widget provides a text or image display. -\o \image cleanlooks-lcdnumber.png +\li \image cleanlooks-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image cleanlooks-lineedit.png +\li \image cleanlooks-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image cleanlooks-dateedit.png +\li \image cleanlooks-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image cleanlooks-timeedit.png +\li \image cleanlooks-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image cleanlooks-datetimeedit.png +\li \image cleanlooks-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image cleanlooks-slider.png +\li \image cleanlooks-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image cleanlooks-combobox.png +\li \image cleanlooks-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image cleanlooks-spinbox.png +\li \image cleanlooks-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image cleanlooks-fontcombobox.png +\li \image cleanlooks-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image cleanlooks-doublespinbox.png +\li \image cleanlooks-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image cleanlooks-horizontalscrollbar.png +\li \image cleanlooks-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image cleanlooks-dial.png +\li \image cleanlooks-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image cleanlooks-textedit.png +\li \image cleanlooks-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image cleanlooks-calendarwidget.png +\li \image cleanlooks-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-gtk.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-gtk.qdoc index 6a7fb5f3b5..820f0b4140 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-gtk.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-gtk.qdoc @@ -41,18 +41,18 @@ \table 100% \row -\o \image gtk-pushbutton.png +\li \image gtk-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image gtk-toolbutton.png +\li \image gtk-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image gtk-checkbox.png +\li \image gtk-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image gtk-radiobutton.png +\li \image gtk-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -60,13 +60,13 @@ \table 100% \row -\o \image gtk-groupbox.png +\li \image gtk-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image gtk-tabwidget.png +\li \image gtk-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image gtk-frame.png +\li \image gtk-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image gtk-toolbox.png +\li \image gtk-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -74,24 +74,24 @@ \table 100% \row -\o \image gtk-listview.png +\li \image gtk-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image gtk-treeview.png +\li \image gtk-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image gtk-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image gtk-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image gtk-progressbar.png +\li \image gtk-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image gtk-label.png +\li \image gtk-label.png The QLabel widget provides a text or image display. -\o \image gtk-lcdnumber.png +\li \image gtk-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -99,43 +99,43 @@ \table 100% \row -\o \image gtk-lineedit.png +\li \image gtk-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image gtk-dateedit.png +\li \image gtk-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image gtk-timeedit.png +\li \image gtk-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image gtk-datetimeedit.png +\li \image gtk-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image gtk-slider.png +\li \image gtk-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image gtk-combobox.png +\li \image gtk-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image gtk-spinbox.png +\li \image gtk-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image gtk-fontcombobox.png +\li \image gtk-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image gtk-doublespinbox.png +\li \image gtk-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image gtk-horizontalscrollbar.png +\li \image gtk-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image gtk-dial.png +\li \image gtk-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image gtk-textedit.png +\li \image gtk-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image gtk-calendarwidget.png +\li \image gtk-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-macintosh.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-macintosh.qdoc index 6eceea114f..488a3f7665 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-macintosh.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-macintosh.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image macintosh-pushbutton.png +\li \image macintosh-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image macintosh-toolbutton.png +\li \image macintosh-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image macintosh-checkbox.png +\li \image macintosh-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image macintosh-radiobutton.png +\li \image macintosh-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image macintosh-groupbox.png +\li \image macintosh-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image macintosh-tabwidget.png +\li \image macintosh-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image macintosh-frame.png +\li \image macintosh-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image macintosh-toolbox.png +\li \image macintosh-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image macintosh-listview.png +\li \image macintosh-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image macintosh-treeview.png +\li \image macintosh-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image macintosh-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image macintosh-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image macintosh-progressbar.png +\li \image macintosh-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image macintosh-label.png +\li \image macintosh-label.png The QLabel widget provides a text or image display. -\o \image macintosh-lcdnumber.png +\li \image macintosh-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image macintosh-lineedit.png +\li \image macintosh-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image macintosh-dateedit.png +\li \image macintosh-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image macintosh-timeedit.png +\li \image macintosh-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image macintosh-datetimeedit.png +\li \image macintosh-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image macintosh-slider.png +\li \image macintosh-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image macintosh-combobox.png +\li \image macintosh-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image macintosh-spinbox.png +\li \image macintosh-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image macintosh-fontcombobox.png +\li \image macintosh-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image macintosh-doublespinbox.png +\li \image macintosh-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image macintosh-horizontalscrollbar.png +\li \image macintosh-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image macintosh-dial.png +\li \image macintosh-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image macintosh-textedit.png +\li \image macintosh-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image macintosh-calendarwidget.png +\li \image macintosh-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-motif.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-motif.qdoc index d059d2282f..5cbffc5516 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-motif.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-motif.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image motif-pushbutton.png +\li \image motif-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image motif-toolbutton.png +\li \image motif-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image motif-checkbox.png +\li \image motif-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image motif-radiobutton.png +\li \image motif-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image motif-groupbox.png +\li \image motif-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image motif-tabwidget.png +\li \image motif-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image motif-frame.png +\li \image motif-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image motif-toolbox.png +\li \image motif-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image motif-listview.png +\li \image motif-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image motif-treeview.png +\li \image motif-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image motif-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image motif-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image motif-progressbar.png +\li \image motif-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image motif-label.png +\li \image motif-label.png The QLabel widget provides a text or image display. -\o \image motif-lcdnumber.png +\li \image motif-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image motif-lineedit.png +\li \image motif-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image motif-dateedit.png +\li \image motif-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image motif-timeedit.png +\li \image motif-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image motif-datetimeedit.png +\li \image motif-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image motif-slider.png +\li \image motif-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image motif-combobox.png +\li \image motif-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image motif-spinbox.png +\li \image motif-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image motif-fontcombobox.png +\li \image motif-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image motif-doublespinbox.png +\li \image motif-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image motif-horizontalscrollbar.png +\li \image motif-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image motif-dial.png +\li \image motif-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image motif-textedit.png +\li \image motif-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image motif-calendarwidget.png +\li \image motif-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-plastique.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-plastique.qdoc index 9a57bd6cbc..359fac8018 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-plastique.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-plastique.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image plastique-pushbutton.png +\li \image plastique-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image plastique-toolbutton.png +\li \image plastique-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image plastique-checkbox.png +\li \image plastique-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image plastique-radiobutton.png +\li \image plastique-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image plastique-groupbox.png +\li \image plastique-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image plastique-tabwidget.png +\li \image plastique-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image plastique-frame.png +\li \image plastique-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image plastique-toolbox.png +\li \image plastique-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image plastique-listview.png +\li \image plastique-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image plastique-treeview.png +\li \image plastique-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image plastique-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image plastique-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image plastique-progressbar.png +\li \image plastique-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image plastique-label.png +\li \image plastique-label.png The QLabel widget provides a text or image display. -\o \image plastique-lcdnumber.png +\li \image plastique-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image plastique-lineedit.png +\li \image plastique-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image plastique-dateedit.png +\li \image plastique-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image plastique-timeedit.png +\li \image plastique-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image plastique-datetimeedit.png +\li \image plastique-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image plastique-slider.png +\li \image plastique-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image plastique-combobox.png +\li \image plastique-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image plastique-spinbox.png +\li \image plastique-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image plastique-fontcombobox.png +\li \image plastique-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image plastique-doublespinbox.png +\li \image plastique-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image plastique-horizontalscrollbar.png +\li \image plastique-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image plastique-dial.png +\li \image plastique-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image plastique-textedit.png +\li \image plastique-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image plastique-calendarwidget.png +\li \image plastique-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-windows.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-windows.qdoc index 83ebce97f5..b118c845c6 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-windows.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-windows.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image windows-pushbutton.png +\li \image windows-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image windows-toolbutton.png +\li \image windows-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image windows-checkbox.png +\li \image windows-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image windows-radiobutton.png +\li \image windows-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image windows-groupbox.png +\li \image windows-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image windows-tabwidget.png +\li \image windows-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image windows-frame.png +\li \image windows-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image windows-toolbox.png +\li \image windows-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image windows-listview.png +\li \image windows-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image windows-treeview.png +\li \image windows-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image windows-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image windows-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image windows-progressbar.png +\li \image windows-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image windows-label.png +\li \image windows-label.png The QLabel widget provides a text or image display. -\o \image windows-lcdnumber.png +\li \image windows-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image windows-lineedit.png +\li \image windows-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image windows-dateedit.png +\li \image windows-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image windows-timeedit.png +\li \image windows-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image windows-datetimeedit.png +\li \image windows-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image windows-slider.png +\li \image windows-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image windows-combobox.png +\li \image windows-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image windows-spinbox.png +\li \image windows-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image windows-fontcombobox.png +\li \image windows-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image windows-doublespinbox.png +\li \image windows-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image windows-horizontalscrollbar.png +\li \image windows-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image windows-dial.png +\li \image windows-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image windows-textedit.png +\li \image windows-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image windows-calendarwidget.png +\li \image windows-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-windowsvista.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-windowsvista.qdoc index e54a4dc399..db1a7cee90 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-windowsvista.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-windowsvista.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image windowsvista-pushbutton.png +\li \image windowsvista-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image windowsvista-toolbutton.png +\li \image windowsvista-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image windowsvista-checkbox.png +\li \image windowsvista-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image windowsvista-radiobutton.png +\li \image windowsvista-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image windowsvista-groupbox.png +\li \image windowsvista-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image windowsvista-tabwidget.png +\li \image windowsvista-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image windowsvista-frame.png +\li \image windowsvista-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image windowsvista-toolbox.png +\li \image windowsvista-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image windowsvista-listview.png +\li \image windowsvista-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image windowsvista-treeview.png +\li \image windowsvista-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image windowsvista-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image windowsvista-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image windowsvista-progressbar.png +\li \image windowsvista-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image windowsvista-label.png +\li \image windowsvista-label.png The QLabel widget provides a text or image display. -\o \image windowsvista-lcdnumber.png +\li \image windowsvista-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image windowsvista-lineedit.png +\li \image windowsvista-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image windowsvista-dateedit.png +\li \image windowsvista-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image windowsvista-timeedit.png +\li \image windowsvista-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image windowsvista-datetimeedit.png +\li \image windowsvista-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image windowsvista-slider.png +\li \image windowsvista-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image windowsvista-combobox.png +\li \image windowsvista-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image windowsvista-spinbox.png +\li \image windowsvista-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image windowsvista-fontcombobox.png +\li \image windowsvista-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image windowsvista-doublespinbox.png +\li \image windowsvista-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image windowsvista-horizontalscrollbar.png +\li \image windowsvista-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image windowsvista-dial.png +\li \image windowsvista-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image windowsvista-textedit.png +\li \image windowsvista-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image windowsvista-calendarwidget.png +\li \image windowsvista-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery-windowsxp.qdoc b/doc/src/widgets/widgets-and-layouts/gallery-windowsxp.qdoc index 3753402c5a..2ade5681e2 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery-windowsxp.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery-windowsxp.qdoc @@ -38,18 +38,18 @@ \table 100% \row -\o \image windowsxp-pushbutton.png +\li \image windowsxp-pushbutton.png \caption The QPushButton widget provides a command button. -\o \image windowsxp-toolbutton.png +\li \image windowsxp-toolbutton.png \caption The QToolButton class provides a quick-access button to commands or options, usually used inside a QToolBar. \endtable \table 100% \row -\o \image windowsxp-checkbox.png +\li \image windowsxp-checkbox.png \caption The QCheckBox widget provides a checkbox with a text label. -\o \image windowsxp-radiobutton.png +\li \image windowsxp-radiobutton.png \caption The QRadioButton widget provides a radio button with a text or pixmap label. \endtable @@ -57,13 +57,13 @@ \table 100% \row -\o \image windowsxp-groupbox.png +\li \image windowsxp-groupbox.png The The QGroupBox widget provides a group box frame with a title. -\o \image windowsxp-tabwidget.png +\li \image windowsxp-tabwidget.png The QTabWidget class provides a stack of tabbed widgets. -\o \image windowsxp-frame.png +\li \image windowsxp-frame.png The QFrame widget provides a simple decorated container for other widgets. -\o \image windowsxp-toolbox.png +\li \image windowsxp-toolbox.png The QToolBox class provides a column of tabbed widget items. \endtable @@ -71,24 +71,24 @@ \table 100% \row -\o \image windowsxp-listview.png +\li \image windowsxp-listview.png The QListView class provides a default model/view implementation of a list/icon view. The QListWidget class provides a classic item-based list/icon view. -\o \image windowsxp-treeview.png +\li \image windowsxp-treeview.png The QTreeView class provides a default model/view implementation of a tree view. The QTreeWidget class provides a classic item-based tree view. -\o \image windowsxp-tableview.png - The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\o -\o +\li \image windowsxp-tableview.png + The QTableView class provides a default model/view implementation of a table view. The QTableWidget class provides a classic item-based table view.\li +\li \endtable \section2 Display Widgets \table 100% \row -\o \image windowsxp-progressbar.png +\li \image windowsxp-progressbar.png The QProgressBar widget provides a horizontal progress bar. -\o \image windowsxp-label.png +\li \image windowsxp-label.png The QLabel widget provides a text or image display. -\o \image windowsxp-lcdnumber.png +\li \image windowsxp-lcdnumber.png The QLCDNumber widget displays a number with LCD-like digits. \endtable @@ -96,43 +96,43 @@ \table 100% \row -\o \image windowsxp-lineedit.png +\li \image windowsxp-lineedit.png The QLineEdit widget is a one-line text editor. -\o \image windowsxp-dateedit.png +\li \image windowsxp-dateedit.png The QDateEdit class provides a widget for editing dates. -\o \image windowsxp-timeedit.png +\li \image windowsxp-timeedit.png The QTimeEdit class provides a widget for editing times. -\o \image windowsxp-datetimeedit.png +\li \image windowsxp-datetimeedit.png The QDateTimeEdit class provides a widget for editing dates and times. \endtable \table 100% \row -\o \image windowsxp-slider.png +\li \image windowsxp-slider.png The QSlider widget provides a vertical or horizontal slider. -\o \image windowsxp-combobox.png +\li \image windowsxp-combobox.png The QComboBox widget is a combined button and pop-up list. -\o \image windowsxp-spinbox.png +\li \image windowsxp-spinbox.png The QSpinBox class provides a spin box widget. \endtable \table 100% \row -\o \image windowsxp-fontcombobox.png +\li \image windowsxp-fontcombobox.png The QFontComboBox widget is a specialized combobox that enables fonts to be selected from a pop-up list containing previews of available fonts. -\o \image windowsxp-doublespinbox.png +\li \image windowsxp-doublespinbox.png The QDoubleSpinBox class provides a spin box widget that allows double precision floating point numbers to be entered. -\o \image windowsxp-horizontalscrollbar.png +\li \image windowsxp-horizontalscrollbar.png The QScrollBar widget provides a vertical or horizontal scroll bar. Here, we show a scroll bar with horizontal orientation. \endtable \table 100% \row -\o \image windowsxp-dial.png +\li \image windowsxp-dial.png The QDial class provides a rounded range control (like a speedometer or potentiometer). -\o \image windowsxp-textedit.png +\li \image windowsxp-textedit.png The QTextEdit class provides a widget that is used to edit and display both plain and rich text. -\o \image windowsxp-calendarwidget.png +\li \image windowsxp-calendarwidget.png The QCalendarWidget class provides a monthly calendar widget that can be used to select dates. \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/gallery.qdoc b/doc/src/widgets/widgets-and-layouts/gallery.qdoc index d82eda4805..a2f4db5a7b 100644 --- a/doc/src/widgets/widgets-and-layouts/gallery.qdoc +++ b/doc/src/widgets/widgets-and-layouts/gallery.qdoc @@ -36,15 +36,15 @@ \table \row - \o \image plastique-tabwidget.png Plastique Style Widget Gallery + \li \image plastique-tabwidget.png Plastique Style Widget Gallery \caption \l{Plastique Style Widget Gallery} The Plastique style is provided by QPlastiqueStyle. - \o \image windowsxp-tabwidget.png Windows XP Style Widget Gallery + \li \image windowsxp-tabwidget.png Windows XP Style Widget Gallery \caption \l{Windows XP Style Widget Gallery} The Windows XP style is provided by QWindowsXPStyle. - \o \image windows-tabwidget.png Windows Style Widget Gallery + \li \image windows-tabwidget.png Windows Style Widget Gallery \caption \l{Windows Style Widget Gallery} The Windows style is provided by QWindowsStyle. @@ -52,15 +52,15 @@ \table \row - \o \image macintosh-tabwidget.png Macintosh Style Widget Gallery + \li \image macintosh-tabwidget.png Macintosh Style Widget Gallery \caption \l{Macintosh Style Widget Gallery} The Macintosh style is provided by QMacStyle. - \o \image cleanlooks-tabwidget.png Cleanlooks Style Widget Gallery + \li \image cleanlooks-tabwidget.png Cleanlooks Style Widget Gallery \caption \l{Cleanlooks Style Widget Gallery} The Cleanlooks style is provided by QCleanlooksStyle. - \o \image windowsvista-tabwidget.png Windows Vista Style Widget Gallery + \li \image windowsvista-tabwidget.png Windows Vista Style Widget Gallery \caption \l{Windows Vista Style Widget Gallery} The Windows Vista style is provided by QWindowsVistaStyle. @@ -68,15 +68,15 @@ \table \row - \o \image gtk-tabwidget.png GTK Style Widget Gallery + \li \image gtk-tabwidget.png GTK Style Widget Gallery \caption \l{GTK Style Widget Gallery} The GTK style is provided by QGtkStyle. - \o \image motif-tabwidget.png Motif Style Widget Gallery + \li \image motif-tabwidget.png Motif Style Widget Gallery \caption \l{Motif Style Widget Gallery} The Motif style is provided by QMotifStyle. - \o \image cde-tabwidget.png CDE Style Widget Gallery + \li \image cde-tabwidget.png CDE Style Widget Gallery \caption \l{CDE Style Widget Gallery} The Common Desktop Environment style is provided by QCDEStyle. diff --git a/doc/src/widgets/widgets-and-layouts/layout.qdoc b/doc/src/widgets/widgets-and-layouts/layout.qdoc index ccc15ef805..6e1a5f70e1 100644 --- a/doc/src/widgets/widgets-and-layouts/layout.qdoc +++ b/doc/src/widgets/widgets-and-layouts/layout.qdoc @@ -63,15 +63,15 @@ is set on a widget in this way, it takes charge of the following tasks: \list - \o Positioning of child widgets. - \o Sensible default sizes for windows. - \o Sensible minimum sizes for windows. - \o Resize handling. - \o Automatic updates when contents change: + \li Positioning of child widgets. + \li Sensible default sizes for windows. + \li Sensible minimum sizes for windows. + \li Resize handling. + \li Automatic updates when contents change: \list - \o Font size, text or other contents of child widgets. - \o Hiding or showing a child widget. - \o Removal of child widgets. + \li Font size, text or other contents of child widgets. + \li Hiding or showing a child widget. + \li Removal of child widgets. \endlist \endlist @@ -95,19 +95,19 @@ create more complex layouts, you can nest layout managers inside each other. \list - \o A QHBoxLayout lays out widgets in a horizontal row, from left to + \li A QHBoxLayout lays out widgets in a horizontal row, from left to right (or right to left for right-to-left languages). \image qhboxlayout-with-5-children.png - \o A QVBoxLayout lays out widgets in a vertical column, from top to + \li A QVBoxLayout lays out widgets in a vertical column, from top to bottom. \image qvboxlayout-with-5-children.png - \o A QGridLayout lays out widgets in a two-dimensional grid. Widgets + \li A QGridLayout lays out widgets in a two-dimensional grid. Widgets can occupy multiple cells. \image qgridlayout-with-5-children.png - \o A QFormLayout lays out widgets in a 2-column descriptive label- + \li A QFormLayout lays out widgets in a 2-column descriptive label- field style. \image qformlayout-with-6-children.png \endlist @@ -176,26 +176,26 @@ When you add widgets to a layout, the layout process works as follows: \list 1 - \o All the widgets will initially be allocated an amount of space in + \li All the widgets will initially be allocated an amount of space in accordance with their QWidget::sizePolicy() and QWidget::sizeHint(). - \o If any of the widgets have stretch factors set, with a value + \li If any of the widgets have stretch factors set, with a value greater than zero, then they are allocated space in proportion to their stretch factor (explained below). - \o If any of the widgets have stretch factors set to zero they will + \li If any of the widgets have stretch factors set to zero they will only get more space if no other widgets want the space. Of these, space is allocated to widgets with an \l{QSizePolicy::Expanding}{Expanding} size policy first. - \o Any widgets that are allocated less space than their minimum size + \li Any widgets that are allocated less space than their minimum size (or minimum size hint if no minimum size is specified) are allocated this minimum size they require. (Widgets don't have to have a minimum size or minimum size hint in which case the stretch factor is their determining factor.) - \o Any widgets that are allocated more space than their maximum size + \li Any widgets that are allocated more space than their maximum size are allocated the maximum size space they require. (Widgets do not have to have a maximum size in which case the stretch factor is their determining factor.) @@ -231,11 +231,11 @@ following mechanisms: \list - \o Reimplement QWidget::sizeHint() to return the preferred size of the + \li Reimplement QWidget::sizeHint() to return the preferred size of the widget. - \o Reimplement QWidget::minimumSizeHint() to return the smallest size + \li Reimplement QWidget::minimumSizeHint() to return the smallest size the widget can have. - \o Call QWidget::setSizePolicy() to specify the space requirements of + \li Call QWidget::setSizePolicy() to specify the space requirements of the widget. \endlist @@ -304,14 +304,14 @@ To write your own layout class, you must define the following: \list - \o A data structure to store the items handled by the layout. Each + \li A data structure to store the items handled by the layout. Each item is a \link QLayoutItem QLayoutItem\endlink. We will use a QList in this example. - \o \l{QLayout::}{addItem()}, how to add items to the layout. - \o \l{QLayout::}{setGeometry()}, how to perform the layout. - \o \l{QLayout::}{sizeHint()}, the preferred size of the layout. - \o \l{QLayout::}{itemAt()}, how to iterate over the layout. - \o \l{QLayout::}{takeAt()}, how to remove items from the layout. + \li \l{QLayout::}{addItem()}, how to add items to the layout. + \li \l{QLayout::}{setGeometry()}, how to perform the layout. + \li \l{QLayout::}{sizeHint()}, the preferred size of the layout. + \li \l{QLayout::}{itemAt()}, how to iterate over the layout. + \li \l{QLayout::}{takeAt()}, how to remove items from the layout. \endlist In most cases, you will also implement \l{QLayout::}{minimumSize()}. @@ -376,16 +376,16 @@ \section2 Further Notes \list - \o This custom layout does not handle height for width. - \o We ignore QLayoutItem::isEmpty(); this means that the layout will + \li This custom layout does not handle height for width. + \li We ignore QLayoutItem::isEmpty(); this means that the layout will treat hidden widgets as visible. - \o For complex layouts, speed can be greatly increased by caching + \li For complex layouts, speed can be greatly increased by caching calculated values. In that case, implement QLayoutItem::invalidate() to mark the cached data is dirty. - \o Calling QLayoutItem::sizeHint(), etc. may be expensive. So, you + \li Calling QLayoutItem::sizeHint(), etc. may be expensive. So, you should store the value in a local variable if you need it again later within in the same function. - \o You should not call QLayoutItem::setGeometry() twice on the same + \li You should not call QLayoutItem::setGeometry() twice on the same item in the same function. This call can be very expensive if the item has several child widgets, because the layout manager must do a complete layout every time. Instead, calculate the geometry and diff --git a/doc/src/widgets/widgets-and-layouts/styles.qdoc b/doc/src/widgets/widgets-and-layouts/styles.qdoc index febe1a8345..b9e3a30333 100644 --- a/doc/src/widgets/widgets-and-layouts/styles.qdoc +++ b/doc/src/widgets/widgets-and-layouts/styles.qdoc @@ -93,10 +93,10 @@ bar. Most draw functions now take four arguments: \list - \o an enum value specifying which graphical element to draw - \o a QStyleOption specifying how and where to render that element - \o a QPainter that should be used to draw the element - \o a QWidget on which the drawing is performed (optional) + \li an enum value specifying which graphical element to draw + \li a QStyleOption specifying how and where to render that element + \li a QPainter that should be used to draw the element + \li a QWidget on which the drawing is performed (optional) \endlist When a widget asks a style to draw an element, it provides the style @@ -309,11 +309,11 @@ following parameters: \list - \o the enum value of the element to draw - \o a QStyleOption which contains the information needed to + \li the enum value of the element to draw + \li a QStyleOption which contains the information needed to draw the element. - \o a QPainter with which to draw the element. - \o a pointer to a QWidget, typically the widget + \li a QPainter with which to draw the element. + \li a pointer to a QWidget, typically the widget that the element is painted on. \endlist @@ -337,27 +337,27 @@ typically takes the same arguments. \list - \o The \l{QStyle::}{subElementRect()} function takes a + \li The \l{QStyle::}{subElementRect()} function takes a \l{QStyle::}{SubElement} enum value, and calculates a bounding rectangle for a sub element. The style uses this function to know where to draw the different parts of an element. This is mainly done for reuse. If you create a new style, you can use the same location of sub elements as the super class. - \o The \l{QStyle::}{subControlRect()} function is used to + \li The \l{QStyle::}{subControlRect()} function is used to calculate bounding rectangles for sub controls in complex controls. When you implement a new style, you reimplement \c subControlRect() and calculate the rectangles that are different from the super class. - \o The \l{QStyle::}{pixelMetric()} function returns a pixel + \li The \l{QStyle::}{pixelMetric()} function returns a pixel metric, which is a style dependent size given in screen pixels. It takes a value of the \l{QStyle::}{PixelMetric} enum and returns the correct measure. Note that pixel metrics do not necessarily have to be static measures, but can be calculated with, for example, the style option. - \o The \l{QStyle::}{hitTestComplexControl()} function returns the + \li The \l{QStyle::}{hitTestComplexControl()} function returns the sub control that the mouse pointer is over in a complex control. Usually, this is simply a matter of using \l{QStyle::}{subControlRect()} to get the bounding rectangles of @@ -588,35 +588,35 @@ \table 90% \header - \o State flag - \o Set + \li State flag + \li Set \row - \o State_Sunken - \o Yes + \li State_Sunken + \li Yes \row - \o State_NoChange - \o No + \li State_NoChange + \li No \row - \o State_On - \o Yes + \li State_On + \li Yes \row - \o State_Off - \o No + \li State_Off + \li No \row - \o State_MouseOver - \o Yes + \li State_MouseOver + \li Yes \row - \o State_Enabled - \o Yes + \li State_Enabled + \li Yes \row - \o State_HasFocus - \o Yes + \li State_HasFocus + \li Yes \row - \o State_KeyboardFocusChange - \o No + \li State_KeyboardFocusChange + \li No \row - \o State_Active - \o Yes + \li State_Active + \li Yes \endtable The QCheckBox paints itself in QWidget::paintEvent() with @@ -714,16 +714,16 @@ The following is given for each widget: \list - \o A table with the members (variables, etc.) of its style option. - \o A table over the state flags (QStyle::StateFlag) that + \li A table with the members (variables, etc.) of its style option. + \li A table over the state flags (QStyle::StateFlag) that can be set on the widget and when the states are set. - \o Its element tree (see section \l{The Style Elements}). - \o An image of the widget in which the elements are outlined. + \li Its element tree (see section \l{The Style Elements}). + \li An image of the widget in which the elements are outlined. \omit This is not written yet - probably never will be either - \o List of style hints that should be checked for the + \li List of style hints that should be checked for the widget. - \o List of standard pixmaps that could be used by the + \li List of standard pixmaps that could be used by the elements. \endomit \endlist @@ -737,7 +737,7 @@ Our approach on styling center on the drawing of the widgets. The calculations of sub elements rectangles, sub controls, and pixel - metrics used \bold during drawing is only listed as contents in + metrics used \b during drawing is only listed as contents in the element trees. Note that there are rectangles and pixel metrics that are only used by widgets. This leaves these calculations untreated in the walkthrough. For instance, the @@ -778,53 +778,53 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_Enabled - \o Set if the widget is not disabled (see + \li State_Enabled + \li Set if the widget is not disabled (see QWidget::setEnabled()) \row - \o State_Focus - \o Set if the widget has focus (see + \li State_Focus + \li Set if the widget has focus (see QWidget::hasFocus()) \row - \o State_KeyobordFocusChange - \o Set when the user changes focus with the keyboard + \li State_KeyobordFocusChange + \li Set when the user changes focus with the keyboard (see Qt::WA_KeyboardFocusChange) \row - \o State_MouseOver - \o Set if the mouse cursor is over the widget + \li State_MouseOver + \li Set if the mouse cursor is over the widget \row - \o State_Active - \o Set if the widget is a child of the active window. + \li State_Active + \li Set if the widget is a child of the active window. \row - \o State_HasEditFocus - \o Set if the widget has the edit focus + \li State_HasEditFocus + \li Set if the widget has the edit focus \endtable The other common members for widgets are: \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o rect - \o The bounding rectangle of the element to draw. This + \li rect + \li The bounding rectangle of the element to draw. This is set to the widget bounding rectangle (QWidget::rect()). \row - \o direction - \o The layout direction; a value of the + \li direction + \li The layout direction; a value of the Qt::LayoutDirection enum. \row - \o palette - \o The QPalette to use when drawing the element. This + \li palette + \li The QPalette to use when drawing the element. This is set to the widgets palette (QWidget::palette()). \row - \o fontMetrics - \o The QFontMetrics to use when drawing text on the + \li fontMetrics + \li The QFontMetrics to use when drawing text on the widget. \endtable @@ -885,38 +885,38 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_Sunken - \o Button is down or menu is pressed shown + \li State_Sunken + \li Button is down or menu is pressed shown \row - \o State_On - \o Button is checked + \li State_On + \li Button is checked \row - \o State_Raised - \o Button is not flat and not pressed down + \li State_Raised + \li Button is not flat and not pressed down \endtable Other members of QStyleOptionButton is: \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o features - \o Flags of the QStyleOptionButton::ButtonFeatures enum, + \li features + \li Flags of the QStyleOptionButton::ButtonFeatures enum, which describes various button properties (see enum) \row - \o icon - \o The buttons QIcon (if any) + \li icon + \li The buttons QIcon (if any) \row - \o iconSize - \o The QSize of the icon + \li iconSize + \li The QSize of the icon \row - \o text - \o a QString with the buttons text + \li text + \li a QString with the buttons text \endtable \section3 Check and Radio Buttons @@ -933,21 +933,21 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_sunken - \o The box is pressed down + \li State_sunken + \li The box is pressed down \row - \o State_NoChange - \o The box is partially checked (for tristate + \li State_NoChange + \li The box is partially checked (for tristate checkboxes.) \row - \o State_On - \o The box is checked + \li State_On + \li The box is checked \row - \o State_Off - \o The box is unchecked + \li State_Off + \li The box is unchecked \endtable See \l{Push Buttons} for a table over other members in the @@ -1017,17 +1017,17 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_Sunken - \o The tab is pressed on with the mouse. + \li State_Sunken + \li The tab is pressed on with the mouse. \row - \o State_Selected - \o If it is the current tab. + \li State_Selected + \li If it is the current tab. \row - \o State_HasFocus - \o The tab bar has focus and the tab is selected + \li State_HasFocus + \li The tab bar has focus and the tab is selected \endtable Note that individual tabs may be disabled even if the tab bar @@ -1037,38 +1037,38 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o cornerWidgets - \o Is flags of the CornerWidget enum, which indicate + \li cornerWidgets + \li Is flags of the CornerWidget enum, which indicate if and which corner widgets the tab bar has. \row - \o icon - \o The QIcon of the tab + \li icon + \li The QIcon of the tab \row - \o iconSize - \o The QSize of the icon + \li iconSize + \li The QSize of the icon \row - \o position - \o A TabPosition enum value that indicates the tabs + \li position + \li A TabPosition enum value that indicates the tabs position on the bar relative to the other tabs. \row - \o row - \o holds which row the tab is in + \li row + \li holds which row the tab is in \row - \o selectedPosition - \o A value of the SelectedPosition enum that indicates + \li selectedPosition + \li A value of the SelectedPosition enum that indicates whether the selected tab is adjacent to or is the tab. \row - \o shape - \o A value of the QTabBar::Shape enum indication + \li shape + \li A value of the QTabBar::Shape enum indication whether the tab has rounded or triangular corners and the orientation of the tab. \row - \o text - \o The tab text + \li text + \li The tab text \endtable The frame for tab widgets use QStyleOptionTabWidgetFrame as @@ -1077,26 +1077,26 @@ \table 90% \header - \o Member - \o content + \li Member + \li content \row - \o leftCornerWidgetSize - \o The QSize of the left corner widget (if any). + \li leftCornerWidgetSize + \li The QSize of the left corner widget (if any). \row - \o rightCornerWidgetSize - \o The QSize of the right corner widget (if any). + \li rightCornerWidgetSize + \li The QSize of the right corner widget (if any). \row - \o lineWidth - \o holds the line with for drawing the panel. + \li lineWidth + \li holds the line with for drawing the panel. \row - \o midLineWith - \o this value is currently always 0. + \li midLineWith + \li this value is currently always 0. \row - \o shape - \o The shape of the tabs on the tab bar. + \li shape + \li The shape of the tabs on the tab bar. \row - \o tabBarSize - \o The QSize of the tab bar. + \li tabBarSize + \li The QSize of the tab bar. \endtable \section3 Scroll Bars @@ -1130,11 +1130,11 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_Horizontal - \o The scroll bar is horizontal + \li State_Horizontal + \li The scroll bar is horizontal \endtable The style option of QScrollBar is QStyleOptionSlider. Its @@ -1144,43 +1144,43 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o maximum - \o the maximum value of the scroll bar + \li maximum + \li the maximum value of the scroll bar \row - \o minimum - \o the minimum value of the scroll bar + \li minimum + \li the minimum value of the scroll bar \row - \o notchTarget - \o the number of pixels between notches + \li notchTarget + \li the number of pixels between notches \row - \o orientation - \o a value of the Qt::Orientation enum that specifies + \li orientation + \li a value of the Qt::Orientation enum that specifies whether the scroll bar is vertical or horizontal \row - \o pageStep - \o the number to increase or decrease the sliders + \li pageStep + \li the number to increase or decrease the sliders value (relative to the size of the slider and its value range) on page steps. \row - \o singleStep - \o the number to increase or decrease the sliders + \li singleStep + \li the number to increase or decrease the sliders value on single (or line) steps \row - \o sliderValue - \o The value of the slider + \li sliderValue + \li The value of the slider \row - \o sliderPosition - \o the position of the slider handle. This is the same + \li sliderPosition + \li the position of the slider handle. This is the same as \c sliderValue if the scroll bar is QAbstractSlider::tracking. If not, the scroll bar does not update its value before the mouse releases the handle. \row - \o upsideDown - \o holds the direction in which the scroll bar + \li upsideDown + \li holds the direction in which the scroll bar increases its value. This is used instead of QStyleOption::direction for all abstract sliders. \endtable @@ -1207,42 +1207,42 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o maximum - \o the maximum value of the slider + \li maximum + \li the maximum value of the slider \row - \o minimum - \o the minimum value of the slider + \li minimum + \li the minimum value of the slider \row - \o notchTarget - \o this is the number of pixels between each notch + \li notchTarget + \li this is the number of pixels between each notch \row - \o orientation - \o a Qt::Orientation enum value that gives whether the + \li orientation + \li a Qt::Orientation enum value that gives whether the slider is vertical or horizontal. \row - \o pageStep - \o a number in slider value to increase or decrease + \li pageStep + \li a number in slider value to increase or decrease for page steps \row - \o singleStep - \o the number to increase or decrease the sliders + \li singleStep + \li the number to increase or decrease the sliders value on single (or line) steps. \row - \o sliderValue - \o the value of the slider. + \li sliderValue + \li the value of the slider. \row - \o sliderPosition - \o the position of the slider given as a slider value. + \li sliderPosition + \li the position of the slider given as a slider value. This will be equal to the \c sliderValue if the slider is \l{QAbstractSlider::}{tracking}; if not, the sliders value will not change until the handle is released with the mouse. \row - \o upsideDown - \o this member is used instead of QStyleOption::direction + \li upsideDown + \li this member is used instead of QStyleOption::direction for all abstract sliders. \endtable @@ -1270,11 +1270,11 @@ \table 90% \header - \o State - \o State Set When + \li State + \li State Set When \row - \o State_Sunken - \o Is set if one of the sub controls CC_SpinUp or + \li State_Sunken + \li Is set if one of the sub controls CC_SpinUp or CC_SpinDown is pressed on with the mouse. \endtable @@ -1282,19 +1282,19 @@ \table 90% \header - \o Property - \o Function + \li Property + \li Function \row - \o frame - \o boolean that is true if the spin box is to draw a + \li frame + \li boolean that is true if the spin box is to draw a frame. \row - \o buttonSymbols - \o Value of the ButtonSymbols enum that decides the + \li buttonSymbols + \li Value of the ButtonSymbols enum that decides the symbol on the up/down buttons. \row - \o stepEnabled - \o A value of the StepEnabled indication which of the + \li stepEnabled + \li A value of the StepEnabled indication which of the spin box buttons are pressed down. \endtable @@ -1326,21 +1326,21 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o icon - \o The title bars icon + \li icon + \li The title bars icon \row - \o text - \o the text for the title bar's label + \li text + \li the text for the title bar's label \row - \o windowFlags - \o flags of the Qt::WindowFlag enum. The window flags + \li windowFlags + \li flags of the Qt::WindowFlag enum. The window flags used by QMdiArea for window management. \row - \o titleBarState - \o this is the QWidget::windowState() of the window + \li titleBarState + \li this is the QWidget::windowState() of the window that contains the title bar. \endtable @@ -1374,44 +1374,44 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_Selected - \o The box is not editable and has focus + \li State_Selected + \li The box is not editable and has focus \row - \o State_Sunken - \o SC_ComboBoxArrow is active + \li State_Sunken + \li SC_ComboBoxArrow is active \row - \o State_on - \o The container (list) of the box is visible + \li State_on + \li The container (list) of the box is visible \endtable The style options other members are: \table \header - \o Member - \o Content + \li Member + \li Content \row - \o currentIcon - \o the icon of the current (selected) item of the + \li currentIcon + \li the icon of the current (selected) item of the combo box. \row - \o currentText - \o the text of the current item in the box. + \li currentText + \li the text of the current item in the box. \row - \o editable - \o holds whether the combo box is editable or not + \li editable + \li holds whether the combo box is editable or not \row - \o frame - \o holds whether the combo box has a frame or not + \li frame + \li holds whether the combo box has a frame or not \row - \o iconSize - \o the size of the current items icon. + \li iconSize + \li the size of the current items icon. \row - \o popupRect - \o the bounding rectangle of the combo box's popup + \li popupRect + \li the bounding rectangle of the combo box's popup list. \endtable @@ -1438,42 +1438,42 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_On - \o The check box is checked + \li State_On + \li The check box is checked \row - \o State_Sunken - \o The checkbox is pressed down + \li State_Sunken + \li The checkbox is pressed down \row - \o State_Off - \o The check box is unchecked (or there is no check box) + \li State_Off + \li The check box is unchecked (or there is no check box) \endtable The remaining members of QStyleOptionGroupBox are: \table \header - \o Member - \o Content + \li Member + \li Content \row - \o features - \o flags of the QStyleOptionFrameV2::FrameFeatures + \li features + \li flags of the QStyleOptionFrameV2::FrameFeatures enum describing the frame of the group box. \row - \o lineWidth - \o the line width with which to draw the panel. This + \li lineWidth + \li the line width with which to draw the panel. This is always 1. \row - \o text - \o the text of the group box. + \li text + \li the text of the group box. \row - \o textAlignment - \o the alignment of the group box title + \li textAlignment + \li the alignment of the group box title \row - \o textColor - \o the QColor of the text + \li textColor + \li the QColor of the text \endtable \section3 Splitters @@ -1487,11 +1487,11 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_Horizontal - \o Set if it is a horizontal splitter + \li State_Horizontal + \li Set if it is a horizontal splitter \endtable QSplitter does not use \l{QStyleOption::}{initFrom()} to set up its @@ -1517,36 +1517,36 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o minimum - \o The minimum value of the bar + \li minimum + \li The minimum value of the bar \row - \o maximum - \o The maximum value of the bar + \li maximum + \li The maximum value of the bar \row - \o progress - \o The current value of the bar + \li progress + \li The current value of the bar \row - \o textAlignment - \o How the text is aligned in the label + \li textAlignment + \li How the text is aligned in the label \row - \o textVisible - \o Whether the label is drawn + \li textVisible + \li Whether the label is drawn \row - \o text - \o The label text + \li text + \li The label text \row - \o orientation - \o Progress bars can be vertical or horizontal + \li orientation + \li Progress bars can be vertical or horizontal \row - \o invertedAppearance - \o The progress is inverted (i.e., right to left in a + \li invertedAppearance + \li The progress is inverted (i.e., right to left in a horizontal bar) \row - \o bottomToTop - \o Boolean that if true, turns the label of vertical + \li bottomToTop + \li Boolean that if true, turns the label of vertical progress bars 90 degrees. \endtable @@ -1578,58 +1578,58 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_AutoRise - \o the tool button has the autoRise property set + \li State_AutoRise + \li the tool button has the autoRise property set \row - \o State_raised - \o the button is not sunken (i.e., by being checked or + \li State_raised + \li the button is not sunken (i.e., by being checked or pressed on with the mouse). \row - \o State_Sunken - \o the button is down + \li State_Sunken + \li the button is down \row - \o State_On - \o the button is checkable and checked. + \li State_On + \li the button is checkable and checked. \endtable QStyleOptionToolButton also contains the following members: \table \header - \o Member - \o Content + \li Member + \li Content \row - \o arrowType - \o a Qt::ArrowType enum value, which contains the + \li arrowType + \li a Qt::ArrowType enum value, which contains the direction of the buttons arrow (if an arrow is to be used in place of an icon) \row - \o features - \o flags of the QStyleOptionToolButton::ButtonFeature + \li features + \li flags of the QStyleOptionToolButton::ButtonFeature enum describing if the button has an arrow, a menu, and/or has a popup-delay. \row - \o font - \o the QFont of the buttons label + \li font + \li the QFont of the buttons label \row - \o icon - \o the QIcon of the tool button + \li icon + \li the QIcon of the tool button \row - \o iconSize - \o the icon size of the button's icon + \li iconSize + \li the icon size of the button's icon \row - \o pos - \o the position of the button, as given by + \li pos + \li the position of the button, as given by QWidget::pos() \row - \o text - \o the text of the button + \li text + \li the text of the button \row - \o toolButtonStyle - \o a Qt::ToolButtonStyle enum value which decides + \li toolButtonStyle + \li a Qt::ToolButtonStyle enum value which decides whether the button shows the icon, the text, or both. \endtable @@ -1677,29 +1677,29 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o features - \o Holds whether the bar is movable in a value of the + \li features + \li Holds whether the bar is movable in a value of the ToolBarFeature, which is either Movable or None. \row - \o lineWidth - \o The width of the tool bar frame. + \li lineWidth + \li The width of the tool bar frame. \row - \o midLineWidth - \o This variable is currently not used and is always + \li midLineWidth + \li This variable is currently not used and is always 0. \row - \o positionOfLine - \o The position of the toolbar line within the toolbar + \li positionOfLine + \li The position of the toolbar line within the toolbar area to which it belongs. \row - \o positionWithinLine - \o The position of the toolbar within the toolbar line. + \li positionWithinLine + \li The position of the toolbar within the toolbar line. \row - \o toolBarArea - \o The toolbar area in which the toolbar lives. + \li toolBarArea + \li The toolbar area in which the toolbar lives. \endtable \section3 Menus @@ -1740,61 +1740,61 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_Selected - \o The mouse is over the action and the action is not + \li State_Selected + \li The mouse is over the action and the action is not a separator. \row - \o State_Sunken - \o The mouse is pressed down on the menu item. + \li State_Sunken + \li The mouse is pressed down on the menu item. \row - \o State_DownArrow - \o Set if the menu item is a menu scroller and it scrolls + \li State_DownArrow + \li Set if the menu item is a menu scroller and it scrolls the menu downwards. \endtable \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o checkType - \o A value of the \l{QStyleOptionMenuItem::}{CheckType} enum, + \li checkType + \li A value of the \l{QStyleOptionMenuItem::}{CheckType} enum, which is either NotCheckable, Exclusive, or NonExclusive. \row - \o checked - \o Boolean that is true if the menu item is checked. + \li checked + \li Boolean that is true if the menu item is checked. \row - \o font - \o The QFont to use for the menu item's text. + \li font + \li The QFont to use for the menu item's text. \row - \o icon - \o the QIcon of the menu item. + \li icon + \li the QIcon of the menu item. \row - \o maxIconWidth - \o The maximum width allowed for the icon + \li maxIconWidth + \li The maximum width allowed for the icon \row - \o menuHasChecableItem - \o Boolean which is true if at least one item in the + \li menuHasChecableItem + \li Boolean which is true if at least one item in the menu is checkable. \row - \o menuItemType - \o The type of the menu item. This a value of the + \li menuItemType + \li The type of the menu item. This a value of the \l{QStyleOptionMenuItem::}{MenuItemType}. \row - \o menuRect - \o The bounding rectangle for the QMenu that the menu + \li menuRect + \li The bounding rectangle for the QMenu that the menu item lives in. \row - \o tabWidth - \o This is the distance between the text of the menu + \li tabWidth + \li This is the distance between the text of the menu item and the shortcut. \row - \o text - \o The text of the menu item. + \li text + \li The text of the menu item. \endtable The setup of the style option for CE_MenuTearOff and @@ -1825,18 +1825,18 @@ \table \header - \o Member - \o Content + \li Member + \li Content \row - \o menuRect - \o the bounding rectangle of the entire menu bar to + \li menuRect + \li the bounding rectangle of the entire menu bar to which the item belongs. \row - \o text - \o the text of the item + \li text + \li the text of the item \row - \o icon - \o the icon of the menu item (it is not common that + \li icon + \li the icon of the menu item (it is not common that styles draw this icon) \endtable @@ -1874,44 +1874,44 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o icon - \o the icon of the header (for section that is being + \li icon + \li the icon of the header (for section that is being drawn). \row - \o iconAlignment - \o the alignment (Qt::Alignment) of the icon in the header. + \li iconAlignment + \li the alignment (Qt::Alignment) of the icon in the header. \row - \o orientation - \o a Qt::Orientation value deciding whether the header + \li orientation + \li a Qt::Orientation value deciding whether the header is the horizontal header above the view or the vertical header on the left. \row - \o position - \o a QStyleOptionHeader::SectionPosition value + \li position + \li a QStyleOptionHeader::SectionPosition value giving the header section's position relative to the other sections. \row - \o section - \o holds the section that is being drawn. + \li section + \li holds the section that is being drawn. \row - \o selectedPosition - \o a QStyleOptionHeader::SelectedPosition value giving + \li selectedPosition + \li a QStyleOptionHeader::SelectedPosition value giving the selected section's position relative to the section that is being painted. \row - \o sortIndicator - \o a QStyleOptionHeader::SortIndicator value that + \li sortIndicator + \li a QStyleOptionHeader::SortIndicator value that describes the direction in which the section's sort indicator should be drawn. \row - \o text - \o the text of the currently drawn section. + \li text + \li the text of the currently drawn section. \row - \o textAlignment - \o the Qt::Alignment of the text within the + \li textAlignment + \li the Qt::Alignment of the text within the headersection. \endtable @@ -1927,22 +1927,22 @@ \table 90% \header - \o State - \o Set When + \li State + \li Set When \row - \o State_Sibling - \o the node in the tree has a sibling (i.e., there is + \li State_Sibling + \li the node in the tree has a sibling (i.e., there is another node in the same column). \row - \o State_Item - \o this branch indicator has an item. + \li State_Item + \li this branch indicator has an item. \row - \o State_Children - \o the branch has children (i.e., a new sub-tree can + \li State_Children + \li the branch has children (i.e., a new sub-tree can be opened at the branch). \row - \o State_Open - \o the branch indicator has an opened sub-tree. + \li State_Open + \li the branch indicator has an opened sub-tree. \endtable The tree view (and tree widget) use the style to draw the branches @@ -1986,14 +1986,14 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o icon - \o the icon on the toolbox tab + \li icon + \li the icon on the toolbox tab \row - \o text - \o the text on the toolbox tab + \li text + \li the text on the toolbox tab \endtable \section3 Size Grip @@ -2014,11 +2014,11 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o corner - \o a Qt::Corner value that describe which corner in a + \li corner + \li a Qt::Corner value that describe which corner in a window (or equivalent) the grip is located. \endtable @@ -2038,15 +2038,15 @@ \table \header - \o Member - \o Content + \li Member + \li Content \row - \o opaque - \o boolean that is true if the rubber band must be + \li opaque + \li boolean that is true if the rubber band must be drawn in an opaque style (i.e., color) \row - \o shape - \o a QRubberBand::Shape enum value that holds the + \li shape + \li a QRubberBand::Shape enum value that holds the shape of the band (which is either a rectangle or a line) \endtable @@ -2076,24 +2076,24 @@ \table 90% \header - \o Member - \o Content + \li Member + \li Content \row - \o closeable - \o boolean that holds whether the dock window can be + \li closeable + \li boolean that holds whether the dock window can be closed \row - \o floatable - \o boolean that holds whether the dock window can + \li floatable + \li boolean that holds whether the dock window can float (i.e., detach from the main window in which it lives) \row - \o movable - \o boolean that holds whether the window is movable + \li movable + \li boolean that holds whether the window is movable (i.e., can move to other dock widget areas) \row - \o title - \o the title text of the dock window + \li title + \li the title text of the dock window \endtable For the buttons, QStyleOptionButton is used (see \l{Tool Buttons} diff --git a/doc/src/widgets/widgets-and-layouts/stylesheet.qdoc b/doc/src/widgets/widgets-and-layouts/stylesheet.qdoc index a0a8652eaf..eaedb847c8 100644 --- a/doc/src/widgets/widgets-and-layouts/stylesheet.qdoc +++ b/doc/src/widgets/widgets-and-layouts/stylesheet.qdoc @@ -51,12 +51,12 @@ Topics: \list - \i \l{Overview} - \i \l{The Style Sheet Syntax} - \i \l{Qt Designer Integration} - \i \l{Customizing Qt Widgets Using Style Sheets} - \i \l{Qt Style Sheets Reference} - \i \l{Qt Style Sheets Examples} + \li \l{Overview} + \li \l{The Style Sheet Syntax} + \li \l{Qt Designer Integration} + \li \l{Customizing Qt Widgets Using Style Sheets} + \li \l{Qt Style Sheets Reference} + \li \l{Qt Style Sheets Examples} \endlist \target overview @@ -111,17 +111,17 @@ will. \table - \row \o \inlineimage stylesheet-coffee-xp.png - \o \inlineimage stylesheet-pagefold.png - \row \o Coffee theme running on Windows XP - \o Pagefold theme running on Windows XP + \row \li \inlineimage stylesheet-coffee-xp.png + \li \inlineimage stylesheet-pagefold.png + \row \li Coffee theme running on Windows XP + \li Pagefold theme running on Windows XP \endtable \table - \row \o \inlineimage stylesheet-coffee-cleanlooks.png - \o \inlineimage stylesheet-pagefold-mac.png - \row \o Coffee theme running on Ubuntu Linux - \o Pagefold theme running on Mac OS X + \row \li \inlineimage stylesheet-coffee-cleanlooks.png + \li \inlineimage stylesheet-pagefold-mac.png + \row \li Coffee theme running on Ubuntu Linux + \li Pagefold theme running on Mac OS X \endtable When a style sheet is active, the QStyle returned by QWidget::style() @@ -199,24 +199,24 @@ \table 100% \header - \o Selector - \o Example - \o Explanation + \li Selector + \li Example + \li Explanation \row - \o Universal Selector - \o \c * - \o Matches all widgets. + \li Universal Selector + \li \c * + \li Matches all widgets. \row - \o Type Selector - \o \c QPushButton - \o Matches instances of QPushButton and of its subclasses. + \li Type Selector + \li \c QPushButton + \li Matches instances of QPushButton and of its subclasses. \row - \o Property Selector - \o \c{QPushButton[flat="false"]} - \o Matches instances of QPushButton that are not + \li Property Selector + \li \c{QPushButton[flat="false"]} + \li Matches instances of QPushButton that are not \l{QPushButton::}{flat}. You may use this selector to test for any Qt \l{Qt's Property System}{property} that supports QVariant::toString() (see the \l{QVariant::}{toString()} @@ -237,29 +237,29 @@ unset the style sheet and set it again. \row - \o Class Selector - \o \c .QPushButton - \o Matches instances of QPushButton, but not of its subclasses. + \li Class Selector + \li \c .QPushButton + \li Matches instances of QPushButton, but not of its subclasses. This is equivalent to \c{*[class~="QPushButton"]}. \row - \o ID \target ID Selector + \li ID \target ID Selector Selector - \o \c{QPushButton#okButton} - \o Matches all QPushButton instances whose + \li \c{QPushButton#okButton} + \li Matches all QPushButton instances whose \l{QObject::objectName}{object name} is \c okButton. \row - \o Descendant Selector - \o \c{QDialog QPushButton} - \o Matches all instances of QPushButton that are descendants + \li Descendant Selector + \li \c{QDialog QPushButton} + \li Matches all instances of QPushButton that are descendants (children, grandchildren, etc.) of a QDialog. \row - \o Child Selector - \o \c{QDialog > QPushButton} - \o Matches all instances of QPushButton that are direct + \li Child Selector + \li \c{QDialog > QPushButton} + \li Matches all instances of QPushButton that are direct children of a QDialog. \endtable @@ -329,7 +329,7 @@ Sub-Control} for a realistic example. \note With complex widgets such as QComboBox and QScrollBar, if one - property or sub-control is customized, \bold{all} the other properties or + property or sub-control is customized, \b{all} the other properties or sub-controls must be customized as well. \section1 Pseudo-States @@ -436,10 +436,10 @@ \e{A selector's specificity is calculated as follows:} \list - \o \e{count the number of ID attributes in the selector (= a)} - \o \e{count the number of other attributes and pseudo-classes in the selector (= b)} - \o \e{count the number of element names in the selector (= c)} - \o \e{ignore pseudo-elements [i.e., \l{subcontrols}].} + \li \e{count the number of ID attributes in the selector (= a)} + \li \e{count the number of other attributes and pseudo-classes in the selector (= b)} + \li \e{count the number of element names in the selector (= c)} + \li \e{ignore pseudo-elements [i.e., \l{subcontrols}].} \endlist \e{Concatenating the three numbers a-b-c (in a number system with a @@ -495,7 +495,7 @@ In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. When using Qt Style Sheets, - a widget does \bold{not} automatically inherit its font and color setting + a widget does \b{not} automatically inherit its font and color setting from its parent widget. For example, consider a QPushButton inside a QGroupBox: @@ -589,11 +589,11 @@ \image stylesheet-boxmodel.png \list - \o The margin falls outside the border. - \o The border is drawn between the margin and the padding. - \o The padding falls inside the border, between the border and + \li The margin falls outside the border. + \li The border is drawn between the margin and the padding. + \li The padding falls inside the border, between the border and the actual contents. - \o The content is what is left from the original widget or + \li The content is what is left from the original widget or subcontrol once we have removed the margin, the border, and the padding. \endlist @@ -636,10 +636,10 @@ The steps to render a rule are as follows: \list - \o Set clip for entire rendering operation (border-radius) - \o Draw the background (background-image) - \o Draw the border (border-image, border) - \o Draw overlay image (image) + \li Set clip for entire rendering operation (border-radius) + \li Draw the background (background-image) + \li Draw the border (border-image, border) + \li Draw overlay image (image) \endlist \target sub controls @@ -650,9 +650,9 @@ followed by the down-arrow sub-control. A QComboBox is thus rendered as follows: \list - \o Render the QComboBox { } rule - \o Render the QComboBox::drop-down { } rule - \o Render the QComboBox::down-arrow { } rule + \li Render the QComboBox { } rule + \li Render the QComboBox::drop-down { } rule + \li Render the QComboBox::down-arrow { } rule \endlist Sub-controls share a parent-child relationship. In the case of QComboBox, @@ -666,7 +666,7 @@ Once positioned, sub-controls can be styled using the \l{box model}. \note With complex widgets such as QComboBox and QScrollBar, if one - property or sub-control is customized, \bold{all} the other properties or + property or sub-control is customized, \b{all} the other properties or sub-controls must be customized as well. */ @@ -691,12 +691,12 @@ \table 100% \header - \o Widget - \o How to Style + \li Widget + \li How to Style \row - \o QAbstractScrollArea \target qabstractscrollarea-widget - \o Supports the \l{box model}. + \li QAbstractScrollArea \target qabstractscrollarea-widget + \li Supports the \l{box model}. All derivatives of QAbstractScrollArea, including QTextEdit, and QAbstractItemView (all item view classes), support @@ -711,8 +711,8 @@ {Customizing QAbstractScrollArea} for an example. \row - \o QCheckBox \target qcheckbox-widget - \o Supports the \l{box model}. The check indicator can be + \li QCheckBox \target qcheckbox-widget + \li Supports the \l{box model}. The check indicator can be styled using the \l{#indicator-sub}{::indicator} subcontrol. By default, the indicator is placed in the Top Left corner of the Contents rectangle of the widget. @@ -725,15 +725,15 @@ {Customizing QCheckBox} for an example. \row - \o QColumnView \target qcolumnview-widget - \o The grip can be styled be using the \l{image-prop}{image} property. + \li QColumnView \target qcolumnview-widget + \li The grip can be styled be using the \l{image-prop}{image} property. The arrow indicators can by styled using the \l{left-arrow-sub}{::left-arrow} subcontrol and the \l{right-arrow-sub}{::right-arrow} subcontrol. \row - \o QComboBox \target qcombobox-widget - \o The frame around the combobox can be styled using the + \li QComboBox \target qcombobox-widget + \li The frame around the combobox can be styled using the \l{box model}. The drop-down button can be styled using the \l{#drop-down-sub}{::drop-down} subcontrol. By default, the drop-down button is placed in the top right corner of the padding @@ -746,16 +746,16 @@ for an example. \row - \o QDateEdit \target qdateedit-widget - \o See \l{#qspinbox-widget}{QSpinBox}. + \li QDateEdit \target qdateedit-widget + \li See \l{#qspinbox-widget}{QSpinBox}. \row - \o QDateTimeEdit \target qdatetimeedit-widget - \o See \l{#qspinbox-widget}{QSpinBox}. + \li QDateTimeEdit \target qdatetimeedit-widget + \li See \l{#qspinbox-widget}{QSpinBox}. \row - \o QDialog \target qdialog-widget - \o Supports only the \l{Qt Style Sheets Reference#background-prop}{background}, + \li QDialog \target qdialog-widget + \li Supports only the \l{Qt Style Sheets Reference#background-prop}{background}, \l{#background-clip-prop}{background-clip} and \l{#background-origin-prop}{background-origin} properties. @@ -763,13 +763,13 @@ widget. \row - \o QDialogButtonBox \target qdialogbuttonbox-widget - \o The layout of buttons can be altered using the + \li QDialogButtonBox \target qdialogbuttonbox-widget + \li The layout of buttons can be altered using the \l{#button-layout-prop}{button-layout} property. \row - \o QDockWidget \target qdockwidget-widget - \o Supports styling of the title bar and the title bar buttons when docked. + \li QDockWidget \target qdockwidget-widget + \li Supports styling of the title bar and the title bar buttons when docked. The dock widget border can be styled using the \l{#border-prop}{border} property. The \l{#title-sub}{::title} subcontrol can be used to customize @@ -792,12 +792,12 @@ {Customizing QDockWidget} for an example. \row - \o QDoubleSpinBox \target qdoublespinbox-widget - \o See \l{#qspinbox-widget}{QSpinBox}. + \li QDoubleSpinBox \target qdoublespinbox-widget + \li See \l{#qspinbox-widget}{QSpinBox}. \row - \o QFrame \target qframe-widget - \o Supports the \l{box model}. + \li QFrame \target qframe-widget + \li Supports the \l{box model}. Since 4.3, setting a stylesheet on a QLabel automatically sets the QFrame::frameStyle property to QFrame::StyledPanel. @@ -806,8 +806,8 @@ for an example. \row - \o QGroupBox \target qgroupbox-widget - \o Supports the \l{box model}. The title can be styled using the + \li QGroupBox \target qgroupbox-widget + \li Supports the \l{box model}. The title can be styled using the \l{#title-sub}{::title} subcontrol. By default, the title is placed depending on QGroupBox::textAlignment. @@ -821,8 +821,8 @@ for an example. \row - \o QHeaderView \target qheaderview-widget - \o Supports the \l{box model}. The sections of the header view are + \li QHeaderView \target qheaderview-widget + \li Supports the \l{box model}. The sections of the header view are styled using the \l{#section-sub}{::section} sub control. The \c{section} Sub-control supports the \l{#middle-ps}{:middle}, \l{#first-ps}{:first}, \l{#last-ps}{:last}, @@ -839,8 +839,8 @@ for an example. \row - \o QLabel \target qlabel-widget - \o Supports the \l{box model}. Does not support the + \li QLabel \target qlabel-widget + \li Supports the \l{box model}. Does not support the \l{#hover-ps}{:hover} pseudo-state. Since 4.3, setting a stylesheet on a QLabel automatically @@ -850,8 +850,8 @@ example (a QLabel derives from QFrame). \row - \o QLineEdit \target qlineedit-widget - \o Support the \l{box model}. + \li QLineEdit \target qlineedit-widget + \li Support the \l{box model}. The color and background of the selected item is styled using \l{#selection-color-prop}{selection-color} and @@ -866,8 +866,8 @@ for an example. \row - \o QListView \target qlistview-widget - \o Supports the \l{box model}. When + \li QListView \target qlistview-widget + \li Supports the \l{box model}. When \l{QAbstractItemView::alternatingRowColors}{alternating row colors} is enabled, the alternating colors can be styled using the \l{#alternate-background-color-prop}{alternate-background-color} @@ -891,12 +891,12 @@ {Customzing QListView} for an example. \row - \o QListWidget \target qlistwidget-widget - \o See \l{#qlistview-widget}{QListView}. + \li QListWidget \target qlistwidget-widget + \li See \l{#qlistview-widget}{QListView}. \row - \o QMainWindow \target qmainwindow-widget - \o Supports styling of the separator + \li QMainWindow \target qmainwindow-widget + \li Supports styling of the separator The separator in a QMainWindow when using QDockWidget is styled using the \l{#separator-sub}{::separator} subcontrol. @@ -905,8 +905,8 @@ for an example. \row - \o QMenu \target qmenu-widget - \o Supports the \l{box model}. + \li QMenu \target qmenu-widget + \li Supports the \l{box model}. Individual items are styled using the \l{#item-sub}{::item} subcontrol. In addition to the usually supported pseudo states, @@ -933,8 +933,8 @@ for an example. \row - \o QMenuBar \target qmenubar-widget - \o Supports the \l{box model}. The \l{#spacing-prop}{spacing} + \li QMenuBar \target qmenubar-widget + \li Supports the \l{box model}. The \l{#spacing-prop}{spacing} property specifies the spacing between menu items. Individual items are styled using the \l{#item-sub}{::item} subcontrol. @@ -946,14 +946,14 @@ for an example. \row - \o QMessageBox \target qmessagebox-widget - \o The \l{#messagebox-text-interaction-flags-prop} + \li QMessageBox \target qmessagebox-widget + \li The \l{#messagebox-text-interaction-flags-prop} {messagebox-text-interaction-flags} property can be used to alter the interaction with text in the message box. \row - \o QProgressBar \target qprogressbar-widget - \o Supports the \l{box model}. The chunks of the progress bar + \li QProgressBar \target qprogressbar-widget + \li Supports the \l{box model}. The chunks of the progress bar can be styled using the \l{#chunk-sub}{::chunk} subcontrol. The chunk is displayed on the Contents rectangle of the widget. @@ -967,8 +967,8 @@ for an example. \row - \o QPushButton \target qpushbutton-widget - \o Supports the \l{box model}. Supports the \l{#default-ps}{:default}, + \li QPushButton \target qpushbutton-widget + \li Supports the \l{box model}. Supports the \l{#default-ps}{:default}, \l{#flat-ps}{:flat}, \l{#checked-ps}{:checked} pseudo states. For QPushButton with a menu, the menu indicator is styled @@ -988,8 +988,8 @@ for an example. \row - \o QRadioButton \target qradiobutton-widget - \o Supports the \l{box model}. The check indicator can be + \li QRadioButton \target qradiobutton-widget + \li Supports the \l{box model}. The check indicator can be styled using the \l{#indicator-sub}{::indicator} subcontrol. By default, the indicator is placed in the Top Left corner of the Contents rectangle of the widget. @@ -1002,8 +1002,8 @@ {Customizing QRadioButton} for an example. \row - \o QScrollBar \target qscrollbar-widget - \o Supports the \l{box model}. The Contents rectangle of the widget + \li QScrollBar \target qscrollbar-widget + \li Supports the \l{box model}. The Contents rectangle of the widget is considered to be the groove over which the slider moves. The extent of the QScrollBar (i.e the width or the height depending on the orientation) is set using the \l{#width-prop}{width} or \l{#height-prop}{height} property @@ -1037,8 +1037,8 @@ for an example. \row - \o QSizeGrip \target qsizegrip-widget - \o Supports the \l{#width-prop}{width}, + \li QSizeGrip \target qsizegrip-widget + \li Supports the \l{#width-prop}{width}, \l{#height-prop}{height}, and \l{#image-prop}{image} properties. @@ -1046,8 +1046,8 @@ for an example. \row - \o QSlider \target qslider-widget - \o Supports the \l{box model}. For horizontal slides, the + \li QSlider \target qslider-widget + \li Supports the \l{box model}. For horizontal slides, the \l{min-width-prop}{min-width} and \l{height-prop}{height} properties must be provided. For vertical sliders, the \l{min-height-prop}{min-height} and \l{width-prop}{width} @@ -1064,8 +1064,8 @@ for an example. \row - \o QSpinBox \target qspinbox-widget - \o The frame of the spin box can be styled using the \l{box + \li QSpinBox \target qspinbox-widget + \li The frame of the spin box can be styled using the \l{box model}. The up button and arrow can be styled using the @@ -1090,16 +1090,16 @@ for an example. \row - \o QSplitter \target qsplitter-widget - \o Supports the \l{box model}. The handle of the splitter + \li QSplitter \target qsplitter-widget + \li Supports the \l{box model}. The handle of the splitter is styled using the \l{#handle-sub}{::handle} subcontrol. See \l{Qt Style Sheets Examples#Customizing QSplitter}{Customizing QSplitter} for an example. \row - \o QStatusBar \target qstatusbar-widget - \o Supports only the \l{Qt Style Sheets Reference#background-prop} + \li QStatusBar \target qstatusbar-widget + \li Supports only the \l{Qt Style Sheets Reference#background-prop} {background} property. The frame for individual items can be style using the \l{#item-sub}{::item} subcontrol. @@ -1108,8 +1108,8 @@ for an example. \row - \o QTabBar \target qtabbar-widget - \o Individual tabs may be styled using the \l{#tab-sub}{::tab} subcontrol. + \li QTabBar \target qtabbar-widget + \li Individual tabs may be styled using the \l{#tab-sub}{::tab} subcontrol. Close buttons using the \l{#close-button-sub}{::close-button} The tabs support the \l{#only-one-ps}{:only-one}, \l{#first-ps}{:first}, @@ -1143,8 +1143,8 @@ for an example. \row - \o QTabWidget \target qtabwidget-widget - \o The frame of the tab widget is styled using the + \li QTabWidget \target qtabwidget-widget + \li The frame of the tab widget is styled using the \l{#pane-sub}{::pane} subcontrol. The left and right corners are styled using the \l{#left-corner-sub}{::left-corner} and \l{#right-corner-sub}{::right-corner} respectively. @@ -1163,8 +1163,8 @@ {Customizing QTabWidget} for an example. \row - \o QTableView \target qtableview-widget - \o Supports the \l{box model}. When + \li QTableView \target qtableview-widget + \li Supports the \l{box model}. When \l{QAbstractItemView::alternatingRowColors}{alternating row colors} is enabled, the alternating colors can be styled using the \l{#alternate-background-color-prop}{alternate-background-color} @@ -1194,12 +1194,12 @@ {Customzing QTableView} for an example. \row - \o QTableWidget \target qtablewidget-widget - \o See \l{#qtableview-widget}{QTableView}. + \li QTableWidget \target qtablewidget-widget + \li See \l{#qtableview-widget}{QTableView}. \row - \o QTextEdit \target qtextedit-widget - \o Supports the \l{box model}. + \li QTextEdit \target qtextedit-widget + \li Supports the \l{box model}. The color and background of selected text is styled using \l{#selection-color-prop}{selection-color} and @@ -1210,12 +1210,12 @@ style scrollable backgrounds. \row - \o QTimeEdit \target qtimeedit-widget - \o See \l{#qspinbox-widget}{QSpinBox}. + \li QTimeEdit \target qtimeedit-widget + \li See \l{#qspinbox-widget}{QSpinBox}. \row - \o QToolBar \target qtoolbar-widget - \o Supports the \l{box model}. + \li QToolBar \target qtoolbar-widget + \li Supports the \l{box model}. The \l{#top-ps}{:top}, \l{#left-ps}{:left}, \l{#right-ps}{:right}, \l{#bottom-ps}{:bottom} pseudo states depending on the area in @@ -1236,8 +1236,8 @@ for an example. \row - \o QToolButton \target qtoolbutton-widget - \o Supports the \l{box model}. + \li QToolButton \target qtoolbutton-widget + \li Supports the \l{box model}. If the QToolButton has a menu, is \l{#menu-indicator-sub}{::menu-indicator} subcontrol can be used to @@ -1266,8 +1266,8 @@ for an example. \row - \o QToolBox \target qtoolbox-widget - \o Supports the \l{box model}. + \li QToolBox \target qtoolbox-widget + \li Supports the \l{box model}. The individual tabs can by styled using the \l{#tab-sub}{::tab} subcontrol. The tabs support the @@ -1278,16 +1278,16 @@ \l{#selected-ps}{:selected} pseudo states. \row - \o QToolTip \target qtooltip-widget - \o Supports the \l{box model}. The \l{#opacity-prop}{opacity} + \li QToolTip \target qtooltip-widget + \li Supports the \l{box model}. The \l{#opacity-prop}{opacity} property controls the opacity of the tooltip. See \l{Qt Style Sheets Examples#Customizing QFrame}{Customizing QFrame} for an example (a QToolTip is a QFrame). \row - \o QTreeView \target qtreeview-widget - \o Supports the \l{box model}. When + \li QTreeView \target qtreeview-widget + \li Supports the \l{box model}. When \l{QAbstractItemView::alternatingRowColors}{alternating row colors} is enabled, the alternating colors can be styled using the \l{#alternate-background-color-prop}{alternate-background-color} @@ -1317,12 +1317,12 @@ for an example to style the branches. \row - \o QTreeWidget \target qtreewidget-widget - \o See \l{#qtreeview-widget}{QTreeView}. + \li QTreeWidget \target qtreewidget-widget + \li See \l{#qtreeview-widget}{QTreeView}. \row - \o QWidget \target qwidget-widget - \o Supports only the \l{Qt Style Sheets Reference#background-prop}{background}, + \li QWidget \target qwidget-widget + \li Supports only the \l{Qt Style Sheets Reference#background-prop}{background}, \l{#background-clip-prop}{background-clip} and \l{#background-origin-prop}{background-origin} properties. @@ -1348,14 +1348,14 @@ \table 100% \header - \o Property - \o Type - \o Description + \li Property + \li Type + \li Description \row - \o \bold{\c alternate-background-color} \target alternate-background-color-prop - \o \l{#Brush}{Brush} \BR - \o The \l{QAbstractItemView::alternatingRowColors} + \li \b{\c alternate-background-color} \target alternate-background-color-prop + \li \l{#Brush}{Brush} \BR + \li The \l{QAbstractItemView::alternatingRowColors} {alternate background color} used in QAbstractItemView subclasses. If this property is not set, the default value is @@ -1370,9 +1370,9 @@ \l{#selection-background-color-prop}{selection-background-color}. \row - \o \bold{\c background} \target background-prop - \o \l{#Background}{Background} - \o Shorthand notation for setting the background. Equivalent + \li \b{\c background} \target background-prop + \li \l{#Background}{Background} + \li Shorthand notation for setting the background. Equivalent to specifying \c background-color, \c background-image, \c background-repeat, and/or \c background-position. @@ -1404,18 +1404,18 @@ and \l{#alternate-background-color-prop}{alternate-background-color}. \row - \o \c background-color \target background-color-prop - \o \l{#Brush}{Brush} \BR - \o The background color used for the widget. + \li \c background-color \target background-color-prop + \li \l{#Brush}{Brush} \BR + \li The background color used for the widget. Examples: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 36 \row - \o \c background-image \target background-image-prop - \o \l{#Url}{Url} - \o The background image used for the widget. Semi-transparent + \li \c background-image \target background-image-prop + \li \l{#Url}{Url} + \li The background image used for the widget. Semi-transparent parts of the image let the \c background-color shine through. @@ -1424,9 +1424,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 37 \row - \o \c background-repeat \target background-repeat-prop - \o \l{#Repeat}{Repeat} - \o Whether and how the background image is repeated to fill + \li \c background-repeat \target background-repeat-prop + \li \l{#Repeat}{Repeat} + \li Whether and how the background image is repeated to fill the \c background-origin rectangle. If this property is not specified, the background image @@ -1437,9 +1437,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 38 \row - \o \c background-position - \o \l{#Alignment}{Alignment} - \o The alignment of the background image within the \c + \li \c background-position + \li \l{#Alignment}{Alignment} + \li The alignment of the background image within the \c background-origin rectangle. If this property is not specified, the alignment is \c @@ -1450,9 +1450,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 39 \row - \o \bold{\c background-attachment} \target background-attachment-prop - \o \l{#Attachment}{Attachment} - \o Determines whether the background-image in a QAbstractScrollArea + \li \b{\c background-attachment} \target background-attachment-prop + \li \l{#Attachment}{Attachment} + \li Determines whether the background-image in a QAbstractScrollArea is scrolled or fixed with respect to the viewport. By default, the background-image scrolls with the viewport. @@ -1463,9 +1463,9 @@ See also \l{Qt Style Sheets Reference#background-prop}{background} \row - \o \bold{\c background-clip} \target background-clip-prop - \o \l{#Origin}{Origin} - \o The widget's rectangle, in which the \c background is drawn. + \li \b{\c background-clip} \target background-clip-prop + \li \l{#Origin}{Origin} + \li The widget's rectangle, in which the \c background is drawn. This property specifies the rectangle to which the \c background-color and \c background-image are clipped. @@ -1487,9 +1487,9 @@ \l{#background-origin-prop}{background-origin} and \l{The Box Model}. \row - \o \bold{\c background-origin} \target background-origin-prop - \o \l{#Origin}{Origin} - \o The widget's background rectangle, to use in conjunction + \li \b{\c background-origin} \target background-origin-prop + \li \l{#Origin}{Origin} + \li The widget's background rectangle, to use in conjunction with \c background-position and \c background-image. This property is supported by QAbstractItemView @@ -1509,9 +1509,9 @@ \l{The Box Model}. \row - \o \bold{\c border} \target border-prop - \o \l{#Border}{Border} - \o Shorthand notation for setting the widget's border. Equivalent + \li \b{\c border} \target border-prop + \li \l{#Border}{Border} + \li Shorthand notation for setting the widget's border. Equivalent to specifying \c border-color, \c border-style, and/or \c border-width. @@ -1526,38 +1526,38 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 43 \row - \o \c border-top - \o \l{#Border}{Border} - \o Shorthand notation for setting the widget's top border. + \li \c border-top + \li \l{#Border}{Border} + \li Shorthand notation for setting the widget's top border. Equivalent to specifying \c border-top-color, \c border-top-style, and/or \c border-top-width. \row - \o \c border-right - \o \l{#Border}{Border} - \o Shorthand notation for setting the widget's right border. + \li \c border-right + \li \l{#Border}{Border} + \li Shorthand notation for setting the widget's right border. Equivalent to specifying \c border-right-color, \c border-right-style, and/or \c border-right-width. \row - \o \c border-bottom - \o \l{#Border}{Border} - \o Shorthand notation for setting the widget's bottom border. + \li \c border-bottom + \li \l{#Border}{Border} + \li Shorthand notation for setting the widget's bottom border. Equivalent to specifying \c border-bottom-color, \c border-bottom-style, and/or \c border-bottom-width. \row - \o \c border-left - \o \l{#Border}{Border} - \o Shorthand notation for setting the widget's left border. + \li \c border-left + \li \l{#Border}{Border} + \li Shorthand notation for setting the widget's left border. Equivalent to specifying \c border-left-color, \c border-left-style, and/or \c border-left-width. \row - \o \bold{\c border-color} \target border-attrs + \li \b{\c border-color} \target border-attrs \target border-color-prop - \o \l{#Box Colors}{Box Colors} - \o The color of all the border's edges. Equivalent to + \li \l{#Box Colors}{Box Colors} + \li The color of all the border's edges. Equivalent to specifying \c border-top-color, \c border-right-color, \c border-bottom-color, and \c border-left-color. @@ -1580,29 +1580,29 @@ \l{#border-image-prop}{border-image}, and \l{The Box Model}. \row - \o \c border-top-color - \o \l{#Brush}{Brush} \BR - \o The color of the border's top edge. + \li \c border-top-color + \li \l{#Brush}{Brush} \BR + \li The color of the border's top edge. \row - \o \c border-right-color - \o \l{#Brush}{Brush} \BR - \o The color of the border's right edge. + \li \c border-right-color + \li \l{#Brush}{Brush} \BR + \li The color of the border's right edge. \row - \o \c border-bottom-color - \o \l{#Brush}{Brush} \BR - \o The color of the border's bottom edge. + \li \c border-bottom-color + \li \l{#Brush}{Brush} \BR + \li The color of the border's bottom edge. \row - \o \c border-left-color - \o \l{#Brush}{Brush} \BR - \o The color of the border's left edge. + \li \c border-left-color + \li \l{#Brush}{Brush} \BR + \li The color of the border's left edge. \row - \o \bold{\c border-image} \target border-image-prop - \o \l{#Border Image}{Border Image} - \o The image used to fill the border. The image is cut into + \li \b{\c border-image} \target border-image-prop + \li \l{#Border Image}{Border Image} + \li The image used to fill the border. The image is cut into nine parts and stretched appropriately if necessary. See \l{#Border Image}{Border Image} for details. @@ -1618,9 +1618,9 @@ \l{The Box Model}. \row - \o \bold{\c border-radius} \target border-radius-prop - \o \l{#Radius}{Radius} - \o The radius of the border's corners. Equivalent to + \li \b{\c border-radius} \target border-radius-prop + \li \l{#Radius}{Radius} + \li The radius of the border's corners. Equivalent to specifying \c border-top-left-radius, \c border-top-right-radius, \c border-bottom-right-radius, and \c border-bottom-left-radius. @@ -1644,32 +1644,32 @@ \l{The Box Model}. \row - \o \c border-top-left-radius - \o \l{#Radius}{Radius} - \o The radius of the border's top-left corner. + \li \c border-top-left-radius + \li \l{#Radius}{Radius} + \li The radius of the border's top-left corner. \row - \o \c border-top-right-radius - \o \l{#Radius}{Radius} - \o The radius of the border's top-right corner. + \li \c border-top-right-radius + \li \l{#Radius}{Radius} + \li The radius of the border's top-right corner. \row - \o \c border-bottom-right-radius - \o \l{#Radius}{Radius} - \o The radius of the border's bottom-right corner. Setting + \li \c border-bottom-right-radius + \li \l{#Radius}{Radius} + \li The radius of the border's bottom-right corner. Setting this property to a positive value results in a rounded corner. \row - \o \c border-bottom-left-radius - \o \l{#Radius}{Radius} - \o The radius of the border's bottom-left corner. Setting this + \li \c border-bottom-left-radius + \li \l{#Radius}{Radius} + \li The radius of the border's bottom-left corner. Setting this property to a positive value results in a rounded corner. \row - \o \bold{\c border-style} \target border-style-prop - \o \l {Border Style} - \o The style of all the border's edges. + \li \b{\c border-style} \target border-style-prop + \li \l {Border Style} + \li The style of all the border's edges. This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, @@ -1688,29 +1688,29 @@ \l{#border-image-prop}{border-image}, and \l{The Box Model}. \row - \o \c border-top-style - \o \l{#Border Style}{Border Style} - \o The style of the border's top edge. + \li \c border-top-style + \li \l{#Border Style}{Border Style} + \li The style of the border's top edge. \row - \o \c border-right-style - \o \l{#Border Style}{Border Style} - \o The style of the border's right edge/ + \li \c border-right-style + \li \l{#Border Style}{Border Style} + \li The style of the border's right edge/ \row - \o \c border-bottom-style - \o \l{#Border Style}{Border Style} - \o The style of the border's bottom edge. + \li \c border-bottom-style + \li \l{#Border Style}{Border Style} + \li The style of the border's bottom edge. \row - \o \c border-left-style - \o \l{#Border Style}{Border Style} - \o The style of the border's left edge. + \li \c border-left-style + \li \l{#Border Style}{Border Style} + \li The style of the border's left edge. \row - \o \bold{\c border-width} \target border-width-prop - \o \l{#Box Lengths}{Box Lengths} - \o The width of the border. Equivalent to setting \c + \li \b{\c border-width} \target border-width-prop + \li \l{#Box Lengths}{Box Lengths} + \li The width of the border. Equivalent to setting \c border-top-width, \c border-right-width, \c border-bottom-width, and \c border-left-width. @@ -1731,29 +1731,29 @@ \l{The Box Model}. \row - \o \c border-top-width - \o \l{#Length}{Length} - \o The width of the border's top edge. + \li \c border-top-width + \li \l{#Length}{Length} + \li The width of the border's top edge. \row - \o \c border-right-width - \o \l{#Length}{Length} - \o The width of the border's right edge. + \li \c border-right-width + \li \l{#Length}{Length} + \li The width of the border's right edge. \row - \o \c border-bottom-width - \o \l{#Length}{Length} - \o The width of the border's bottom edge. + \li \c border-bottom-width + \li \l{#Length}{Length} + \li The width of the border's bottom edge. \row - \o \c border-left-width - \o \l{#Length}{Length} - \o The width of the border's left edge. + \li \c border-left-width + \li \l{#Length}{Length} + \li The width of the border's left edge. \row - \o \bold{\c bottom} \target bottom-prop - \o \l{#Length}{Length} - \o If \l{#position-prop}{position} is \c relative (the + \li \b{\c bottom} \target bottom-prop + \li \l{#Length}{Length} + \li If \l{#position-prop}{position} is \c relative (the default), moves a \l{subcontrol} by a certain offset up; specifying \tt{bottom: \e{y}} is then equivalent to specifying \tt{\l{Qt Style Sheets Reference#top-prop}{top}: -\e{y}}. @@ -1772,9 +1772,9 @@ \l{Qt Style Sheets Reference#top-prop}{top}. \row - \o \bold{\c button-layout} \target button-layout-prop - \o \l{#Number}{Number} - \o The layout of buttons in a QDialogButtonBox or + \li \b{\c button-layout} \target button-layout-prop + \li \l{#Number}{Number} + \li The layout of buttons in a QDialogButtonBox or a QMessageBox. The possible values are 0 (\l{QDialogButtonBox::}{WinLayout}), 1 (\l{QDialogButtonBox::}{MacLayout}), 2 @@ -1790,9 +1790,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 49 \row - \o \bold{\c color} \target color-prop - \o \l{#Brush}{Brush} \BR - \o The color used to render text. + \li \b{\c color} \target color-prop + \li \l{#Brush}{Brush} \BR + \li The color used to render text. This property is supported by all widgets that respect the \l QWidget::palette. @@ -1809,9 +1809,9 @@ \l{#selection-color-prop}{selection-color}. \row - \o \bold{\c dialogbuttonbox-buttons-have-icons} - \o \l{#Boolean}{Boolean} - \o Whether the buttons in a QDialogButtonBox show icons + \li \b{\c dialogbuttonbox-buttons-have-icons} + \li \l{#Boolean}{Boolean} + \li Whether the buttons in a QDialogButtonBox show icons If this property is set to 1, the buttons of a QDialogButtonBox show icons; if it is set to 0, the icons are not shown. @@ -1827,9 +1827,9 @@ \omit \row - \o \bold{\c etch-disabled-text}* - \o \l{#Boolean}{Boolean} - \o Whether disabled text is drawn etched. + \li \b{\c etch-disabled-text}* + \li \l{#Boolean}{Boolean} + \li Whether disabled text is drawn etched. If this property is not specified, it defaults to the value specified by the current style for the @@ -1841,9 +1841,9 @@ \endomit \row - \o \bold{\c font} \target font-prop - \o \l{#Font}{Font} - \o Shorthand notation for setting the text's font. Equivalent + \li \b{\c font} \target font-prop + \li \l{#Font}{Font} + \li Shorthand notation for setting the text's font. Equivalent to specifying \c font-family, \c font-size, \c font-style, and/or \c font-weight. @@ -1858,18 +1858,18 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 53 \row - \o \c font-family - \o String - \o The font family. + \li \c font-family + \li String + \li The font family. Example: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 54 \row - \o \c font-size - \o \l{#Font Size}{Font Size} - \o The font size. In this version of Qt, only pt and px metrics are + \li \c font-size + \li \l{#Font Size}{Font Size} + \li The font size. In this version of Qt, only pt and px metrics are supported. Example: @@ -1877,23 +1877,23 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 55 \row - \o \c font-style - \o \l {Font Style} - \o The font style. + \li \c font-style + \li \l {Font Style} + \li The font style. Example: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 56 \row - \o \c font-weight - \o \l{#Font Weight}{Font Weight} - \o The weight of the font. + \li \c font-weight + \li \l{#Font Weight}{Font Weight} + \li The weight of the font. \row - \o \bold{\c gridline-color}* \target gridline-color-prop - \o \l{#Color}{Color} \BR - \o The color of the grid line in a QTableView. + \li \b{\c gridline-color}* \target gridline-color-prop + \li \l{#Color}{Color} \BR + \li The color of the grid line in a QTableView. If this property is not specified, it defaults to the value specified by the current style for the @@ -1904,9 +1904,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 57 \row - \o \bold{\c height} \target height-prop - \o \l{#Length}{Length} - \o The height of a \l{subcontrol} (or in some case, a widget). + \li \b{\c height} \target height-prop + \li \l{#Length}{Length} + \li The height of a \l{subcontrol} (or in some case, a widget). If this property is not specified, it defaults to a value that depends on the subcontrol/widget and on the current style. @@ -1923,27 +1923,27 @@ See also \l{#width-prop}{width}. \row - \o \bold{\c icon-size} \target icon-size-prop - \o \l{#Length}{Length} - \o The width and height of the icon in a widget. + \li \b{\c icon-size} \target icon-size-prop + \li \l{#Length}{Length} + \li The width and height of the icon in a widget. The icon size of the following widgets can be set using this property. \list - \i QCheckBox - \i QListView - \i QPushButton - \i QRadioButton - \i QTabBar - \i QToolBar - \i QToolBox - \i QTreeView + \li QCheckBox + \li QListView + \li QPushButton + \li QRadioButton + \li QTabBar + \li QToolBar + \li QToolBox + \li QTreeView \endlist \row - \o \bold{\c image}* \target image-prop - \o \l{#Url}{Url}+ - \o The image that is drawn in the contents rectangle of a + \li \b{\c image}* \target image-prop + \li \l{#Url}{Url}+ + \li The image that is drawn in the contents rectangle of a \l{subcontrol}. The image property accepts a list of \l{#Url}{Url}s or @@ -1969,15 +1969,15 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 59 \row - \o \bold{\c image-position} \target image-position-prop - \o \l{#Alignment}{alignment} - \o In Qt 4.3 and later, the alignment of the image image's position can be specified + \li \b{\c image-position} \target image-position-prop + \li \l{#Alignment}{alignment} + \li In Qt 4.3 and later, the alignment of the image image's position can be specified using relative or absolute position. \row - \o \bold{\c left} \target left-prop - \o \l{#Length}{Length} - \o If \l{#position-prop}{position} is \c relative (the + \li \b{\c left} \target left-prop + \li \l{#Length}{Length} + \li If \l{#position-prop}{position} is \c relative (the default), moves a \l{subcontrol} by a certain offset to the right. @@ -1996,9 +1996,9 @@ \l{#bottom-prop}{bottom}. \row - \o \bold{\c lineedit-password-character*} \target lineedit-password-character-prop - \o \l{#Number}{Number} - \o The QLineEdit password character as a Unicode number. + \li \b{\c lineedit-password-character*} \target lineedit-password-character-prop + \li \l{#Number}{Number} + \li The QLineEdit password character as a Unicode number. If this property is not specified, it defaults to the value specified by the current style for the @@ -2009,9 +2009,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 61 \row - \o \bold{\c margin} \target margin-prop - \o \l {Box Lengths} - \o The widget's margins. Equivalent to specifying \c + \li \b{\c margin} \target margin-prop + \li \l {Box Lengths} + \li The widget's margins. Equivalent to specifying \c margin-top, \c margin-right, \c margin-bottom, and \c margin-left. @@ -2031,29 +2031,29 @@ \l{#spacing-prop}{spacing}, and \l{The Box Model}. \row - \o \c margin-top - \o \l{#Length}{Length} - \o The widget's top margin. + \li \c margin-top + \li \l{#Length}{Length} + \li The widget's top margin. \row - \o \c margin-right - \o \l{#Length}{Length} - \o The widget's right margin. + \li \c margin-right + \li \l{#Length}{Length} + \li The widget's right margin. \row - \o \c margin-bottom - \o \l{#Length}{Length} - \o The widget's bottom margin. + \li \c margin-bottom + \li \l{#Length}{Length} + \li The widget's bottom margin. \row - \o \c margin-left - \o \l{#Length}{Length} - \o The widget's left margin. + \li \c margin-left + \li \l{#Length}{Length} + \li The widget's left margin. \row - \o \bold{\c max-height} \target max-height-prop - \o \l{#Length}{Length} - \o The widget's or a subcontrol's maximum height. + \li \b{\c max-height} \target max-height-prop + \li \l{#Length}{Length} + \li The widget's or a subcontrol's maximum height. This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, @@ -2071,9 +2071,9 @@ See also \l{#max-width-prop}{max-width}. \row - \o \bold{\c max-width} \target max-width-prop - \o \l{#Length}{Length} - \o The widget's or a subcontrol's maximum width. + \li \b{\c max-width} \target max-width-prop + \li \l{#Length}{Length} + \li The widget's or a subcontrol's maximum width. This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, @@ -2092,9 +2092,9 @@ \row - \o \bold{\c messagebox-text-interaction-flags*} \target messagebox-text-interaction-flags-prop - \o \l{#Number}{Number} - \o The interaction behavior for text in a message box. + \li \b{\c messagebox-text-interaction-flags*} \target messagebox-text-interaction-flags-prop + \li \l{#Number}{Number} + \li The interaction behavior for text in a message box. Possible values are based on Qt::TextInteractionFlags. If this property is not specified, it defaults to the @@ -2107,9 +2107,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 65 \row - \o \bold{\c min-height} \target min-height-prop - \o \l{#Length}{Length} - \o The widget's or a subcontrol's minimum height. + \li \b{\c min-height} \target min-height-prop + \li \l{#Length}{Length} + \li The widget's or a subcontrol's minimum height. This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, @@ -2130,9 +2130,9 @@ See also \l{#min-width-prop}{min-width}. \row - \o \bold{\c min-width} \target min-width-prop - \o \l{#Length}{Length} - \o The widget's or a subcontrol's minimum width. + \li \b{\c min-width} \target min-width-prop + \li \l{#Length}{Length} + \li The widget's or a subcontrol's minimum width. This property is supported by QAbstractItemView subclasses, QAbstractSpinBox subclasses, QCheckBox, @@ -2153,9 +2153,9 @@ See also \l{#min-height-prop}{min-height}. \row - \o \bold{\c opacity*} \target opacity-prop - \o \l{#Number}{Number} - \o The opacity for a widget. Possible values are from 0 + \li \b{\c opacity*} \target opacity-prop + \li \l{#Number}{Number} + \li The opacity for a widget. Possible values are from 0 (transparent) to 255 (opaque). For the moment, this is only supported for \l{QToolTip}{tooltips}. @@ -2168,9 +2168,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 68 \row - \o \bold{\c padding} \target padding-prop - \o \l{#Box Lengths}{Box Lengths} - \o The widget's padding. Equivalent to specifying \c + \li \b{\c padding} \target padding-prop + \li \l{#Box Lengths}{Box Lengths} + \li The widget's padding. Equivalent to specifying \c padding-top, \c padding-right, \c padding-bottom, and \c padding-left. @@ -2190,37 +2190,37 @@ \l{#spacing-prop}{spacing}, and \l{The Box Model}. \row - \o \c padding-top - \o \l{#Length}{Length} - \o The widget's top padding. + \li \c padding-top + \li \l{#Length}{Length} + \li The widget's top padding. \row - \o \c padding-right - \o \l{#Length}{Length} - \o The widget's right padding. + \li \c padding-right + \li \l{#Length}{Length} + \li The widget's right padding. \row - \o \c padding-bottom - \o \l{#Length}{Length} - \o The widget's bottom padding. + \li \c padding-bottom + \li \l{#Length}{Length} + \li The widget's bottom padding. \row - \o \c padding-left - \o \l{#Length}{Length} - \o The widget's left padding. + \li \c padding-left + \li \l{#Length}{Length} + \li The widget's left padding. \row - \o \bold{\c paint-alternating-row-colors-for-empty-area} + \li \b{\c paint-alternating-row-colors-for-empty-area} \target paint-alternating-row-colors-for-empty-area-prop - \o \c bool - \o Whether the QTreeView paints alternating row colors for the empty + \li \c bool + \li Whether the QTreeView paints alternating row colors for the empty area (i.e the area where there are no items) \row - \o \bold{\c position} \target position-prop - \o \c relative \BR + \li \b{\c position} \target position-prop + \li \c relative \BR | \c absolute - \o Whether offsets specified using \l{Qt Style Sheets Reference#left-prop}{left}, + \li Whether offsets specified using \l{Qt Style Sheets Reference#left-prop}{left}, \l{#right-prop}{right}, \l{Qt Style Sheets Reference#top-prop}{top}, and \l{#bottom-prop}{bottom} are relative or absolute coordinates. @@ -2229,9 +2229,9 @@ relative. \row - \o \bold{\c right} \target right-prop - \o \l{#Length}{Length} - \o If \l{#position-prop}{position} is \c relative (the + \li \b{\c right} \target right-prop + \li \l{#Length}{Length} + \li If \l{#position-prop}{position} is \c relative (the default), moves a \l{subcontrol} by a certain offset to the left; specifying \tt{right: \e{x}} is then equivalent to specifying \tt{\l{Qt Style Sheets Reference#left-prop}{left}: -\e{x}}. @@ -2249,9 +2249,9 @@ \l{#bottom-prop}{bottom}. \row - \o \bold{\c selection-background-color*} \target selection-background-color-prop - \o \l{#Brush}{Brush} \BR - \o The background of selected text or items. + \li \b{\c selection-background-color*} \target selection-background-color-prop + \li \l{#Brush}{Brush} \BR + \li The background of selected text or items. This property is supported by all widgets that respect the \l QWidget::palette and that show selection text. @@ -2268,9 +2268,9 @@ \l{Qt Style Sheets Reference#background-prop}{background}. \row - \o \bold{\c selection-color*} \target selection-color-prop - \o \l{#Brush}{Brush} \BR - \o The foreground of selected text or items. + \li \b{\c selection-color*} \target selection-color-prop + \li \l{#Brush}{Brush} \BR + \li The foreground of selected text or items. This property is supported by all widgets that respect the \l QWidget::palette and that show selection text. @@ -2288,9 +2288,9 @@ and \l{#color-prop}{color}. \row - \o \bold{\c show-decoration-selected*} \target show-decoration-selected-prop - \o \l{#Boolean}{Boolean} - \o Controls whether selections in a QListView cover the + \li \b{\c show-decoration-selected*} \target show-decoration-selected-prop + \li \l{#Boolean}{Boolean} + \li Controls whether selections in a QListView cover the entire row or just the extent of the text. If this property is not specified, it defaults to the @@ -2303,9 +2303,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 73 \row - \o \bold{\c spacing*} \target spacing-prop - \o \l{#Length}{Length} - \o Internal spacing in the widget. + \li \b{\c spacing*} \target spacing-prop + \li \l{#Length}{Length} + \li Internal spacing in the widget. This property is supported by QCheckBox, checkable \l{QGroupBox}es, QMenuBar, and QRadioButton. @@ -2321,9 +2321,9 @@ \l{#margin-prop}{margin}. \row - \o \bold{\c subcontrol-origin*} \target subcontrol-origin-prop - \o \l{#Origin}{Origin} - \o The origin rectangle of the \l subcontrol within the + \li \b{\c subcontrol-origin*} \target subcontrol-origin-prop + \li \l{#Origin}{Origin} + \li The origin rectangle of the \l subcontrol within the parent element. If this property is not specified, the default is \c @@ -2337,9 +2337,9 @@ \l{Qt Style Sheets Reference#subcontrol-position-prop}{subcontrol-position}. \row - \o \bold{\c subcontrol-position*} \target subcontrol-position-prop - \o \l{#Alignment}{Alignment} - \o The alignment of the \l subcontrol within the origin + \li \b{\c subcontrol-position*} \target subcontrol-position-prop + \li \l{#Alignment}{Alignment} + \li The alignment of the \l subcontrol within the origin rectangle specified by \l{Qt Style Sheets Reference#subcontrol-origin-prop} {subcontrol-origin}. @@ -2354,9 +2354,9 @@ \l{Qt Style Sheets Reference#subcontrol-origin-prop}{subcontrol-origin}. \row - \o \bold{\c text-align} \target text-align-prop - \o \l{#Alignment}{Alignment} - \o The alignment of text and icon within the contents of the widget. + \li \b{\c text-align} \target text-align-prop + \li \l{#Alignment}{Alignment} + \li The alignment of text and icon within the contents of the widget. If this value is not specified, it defaults to the value that depends on the native style. @@ -2369,17 +2369,17 @@ and QProgressBar. \row - \o \bold{\c text-decoration} - \o \c none \BR + \li \b{\c text-decoration} + \li \c none \BR \c underline \BR \c overline \BR \c line-through - \o Additional text effects + \li Additional text effects \row - \o \bold{\c top} \target top-prop - \o \l{#Length}{Length} - \o If \l{#position-prop}{position} is \c relative (the + \li \b{\c top} \target top-prop + \li \l{#Length}{Length} + \li If \l{#position-prop}{position} is \c relative (the default), moves a \l{subcontrol} by a certain offset down. @@ -2398,9 +2398,9 @@ \l{#bottom-prop}{bottom}. \row - \o \bold{\c width} \target width-prop - \o \l{#Length}{Length} - \o The width of a \l{subcontrol} (or a widget in some cases). + \li \b{\c width} \target width-prop + \li \l{#Length}{Length} + \li The width of a \l{subcontrol} (or a widget in some cases). If this property is not specified, it defaults to a value that depends on the subcontrol/widget and on the current style. @@ -2430,222 +2430,222 @@ \table 100% \header - \o Name - \o QStyle::StandardPixmap + \li Name + \li QStyle::StandardPixmap \row - \o backward-icon - \o QStyle::SP_ArrowBack + \li backward-icon + \li QStyle::SP_ArrowBack \row - \o cd-icon - \o QStyle::SP_DriveCDIcon + \li cd-icon + \li QStyle::SP_DriveCDIcon \row - \o computer-icon - \o QStyle::SP_ComputerIcon + \li computer-icon + \li QStyle::SP_ComputerIcon \row - \o desktop-icon - \o QStyle::SP_DesktopIcon + \li desktop-icon + \li QStyle::SP_DesktopIcon \row - \o dialog-apply-icon - \o QStyle::SP_DialogApplyButton + \li dialog-apply-icon + \li QStyle::SP_DialogApplyButton \row - \o dialog-cancel-icon - \o QStyle::SP_DialogCancelButton + \li dialog-cancel-icon + \li QStyle::SP_DialogCancelButton \row - \o dialog-close-icon - \o QStyle::SP_DialogCloseButton + \li dialog-close-icon + \li QStyle::SP_DialogCloseButton \row - \o dialog-discard-icon - \o QStyle::SP_DialogDiscardButton + \li dialog-discard-icon + \li QStyle::SP_DialogDiscardButton \row - \o dialog-help-icon - \o QStyle::SP_DialogHelpButton + \li dialog-help-icon + \li QStyle::SP_DialogHelpButton \row - \o dialog-no-icon - \o QStyle::SP_DialogNoButton + \li dialog-no-icon + \li QStyle::SP_DialogNoButton \row - \o dialog-ok-icon - \o QStyle::SP_DialogOkButton + \li dialog-ok-icon + \li QStyle::SP_DialogOkButton \row - \o dialog-open-icon - \o QStyle::SP_DialogOpenButton + \li dialog-open-icon + \li QStyle::SP_DialogOpenButton \row - \o dialog-reset-icon - \o QStyle::SP_DialogResetButton + \li dialog-reset-icon + \li QStyle::SP_DialogResetButton \row - \o dialog-save-icon - \o QStyle::SP_DialogSaveButton + \li dialog-save-icon + \li QStyle::SP_DialogSaveButton \row - \o dialog-yes-icon - \o QStyle::SP_DialogYesButton + \li dialog-yes-icon + \li QStyle::SP_DialogYesButton \row - \o directory-closed-icon - \o QStyle::SP_DirClosedIcon + \li directory-closed-icon + \li QStyle::SP_DirClosedIcon \row - \o directory-icon - \o QStyle::SP_DirIcon + \li directory-icon + \li QStyle::SP_DirIcon \row - \o directory-link-icon - \o QStyle::SP_DirLinkIcon + \li directory-link-icon + \li QStyle::SP_DirLinkIcon \row - \o directory-open-icon - \o QStyle::SP_DirOpenIcon + \li directory-open-icon + \li QStyle::SP_DirOpenIcon \row - \o dockwidget-close-icon - \o QStyle::SP_DockWidgetCloseButton + \li dockwidget-close-icon + \li QStyle::SP_DockWidgetCloseButton \row - \o downarrow-icon - \o QStyle::SP_ArrowDown + \li downarrow-icon + \li QStyle::SP_ArrowDown \row - \o dvd-icon - \o QStyle::SP_DriveDVDIcon + \li dvd-icon + \li QStyle::SP_DriveDVDIcon \row - \o file-icon - \o QStyle::SP_FileIcon + \li file-icon + \li QStyle::SP_FileIcon \row - \o file-link-icon - \o QStyle::SP_FileLinkIcon + \li file-link-icon + \li QStyle::SP_FileLinkIcon \omit \row - \o filedialog-backward-icon - \o QStyle::SP_FileDialogBack + \li filedialog-backward-icon + \li QStyle::SP_FileDialogBack \endomit \row - \o filedialog-contentsview-icon - \o QStyle::SP_FileDialogContentsView + \li filedialog-contentsview-icon + \li QStyle::SP_FileDialogContentsView \row - \o filedialog-detailedview-icon - \o QStyle::SP_FileDialogDetailedView + \li filedialog-detailedview-icon + \li QStyle::SP_FileDialogDetailedView \row - \o filedialog-end-icon - \o QStyle::SP_FileDialogEnd + \li filedialog-end-icon + \li QStyle::SP_FileDialogEnd \row - \o filedialog-infoview-icon - \o QStyle::SP_FileDialogInfoView + \li filedialog-infoview-icon + \li QStyle::SP_FileDialogInfoView \row - \o filedialog-listview-icon - \o QStyle::SP_FileDialogListView + \li filedialog-listview-icon + \li QStyle::SP_FileDialogListView \row - \o filedialog-new-directory-icon - \o QStyle::SP_FileDialogNewFolder + \li filedialog-new-directory-icon + \li QStyle::SP_FileDialogNewFolder \row - \o filedialog-parent-directory-icon - \o QStyle::SP_FileDialogToParent + \li filedialog-parent-directory-icon + \li QStyle::SP_FileDialogToParent \row - \o filedialog-start-icon - \o QStyle::SP_FileDialogStart + \li filedialog-start-icon + \li QStyle::SP_FileDialogStart \row - \o floppy-icon - \o QStyle::SP_DriveFDIcon + \li floppy-icon + \li QStyle::SP_DriveFDIcon \row - \o forward-icon - \o QStyle::SP_ArrowForward + \li forward-icon + \li QStyle::SP_ArrowForward \row - \o harddisk-icon - \o QStyle::SP_DriveHDIcon + \li harddisk-icon + \li QStyle::SP_DriveHDIcon \row - \o home-icon - \o QStyle::SP_DirHomeIcon + \li home-icon + \li QStyle::SP_DirHomeIcon \row - \o leftarrow-icon - \o QStyle::SP_ArrowLeft + \li leftarrow-icon + \li QStyle::SP_ArrowLeft \row - \o messagebox-critical-icon - \o QStyle::SP_MessageBoxCritical + \li messagebox-critical-icon + \li QStyle::SP_MessageBoxCritical \row - \o messagebox-information-icon - \o QStyle::SP_MessageBoxInformation + \li messagebox-information-icon + \li QStyle::SP_MessageBoxInformation \row - \o messagebox-question-icon - \o QStyle::SP_MessageBoxQuestion + \li messagebox-question-icon + \li QStyle::SP_MessageBoxQuestion \row - \o messagebox-warning-icon - \o QStyle::SP_MessageBoxWarning + \li messagebox-warning-icon + \li QStyle::SP_MessageBoxWarning \row - \o network-icon - \o QStyle::SP_DriveNetIcon + \li network-icon + \li QStyle::SP_DriveNetIcon \row - \o rightarrow-icon - \o QStyle::SP_ArrowRight + \li rightarrow-icon + \li QStyle::SP_ArrowRight \row - \o titlebar-contexthelp-icon - \o QStyle::SP_TitleBarContextHelpButton + \li titlebar-contexthelp-icon + \li QStyle::SP_TitleBarContextHelpButton \row - \o titlebar-maximize-icon - \o QStyle::SP_TitleBarMaxButton + \li titlebar-maximize-icon + \li QStyle::SP_TitleBarMaxButton \row - \o titlebar-menu-icon - \o QStyle::SP_TitleBarMenuButton + \li titlebar-menu-icon + \li QStyle::SP_TitleBarMenuButton \row - \o titlebar-minimize-icon - \o QStyle::SP_TitleBarMinButton + \li titlebar-minimize-icon + \li QStyle::SP_TitleBarMinButton \row - \o titlebar-normal-icon - \o QStyle::SP_TitleBarNormalButton + \li titlebar-normal-icon + \li QStyle::SP_TitleBarNormalButton \row - \o titlebar-shade-icon - \o QStyle::SP_TitleBarShadeButton + \li titlebar-shade-icon + \li QStyle::SP_TitleBarShadeButton \row - \o titlebar-unshade-icon - \o QStyle::SP_TitleBarUnshadeButton + \li titlebar-unshade-icon + \li QStyle::SP_TitleBarUnshadeButton \row - \o trash-icon - \o QStyle::SP_TrashIcon + \li trash-icon + \li QStyle::SP_TrashIcon \row - \o uparrow-icon - \o QStyle::SP_ArrowUp + \li uparrow-icon + \li QStyle::SP_ArrowUp \endtable @@ -2656,59 +2656,59 @@ \table 100% \header - \o Type - \o Syntax - \o Description + \li Type + \li Syntax + \li Description \row - \o \bold Alignment \target Alignment - \o \{ \c top \BR + \li \b Alignment \target Alignment + \li \{ \c top \BR | \c bottom \BR | \c left \BR | \c right \BR | \c center \}* - \o Horizontal and/or vertical alignment. + \li Horizontal and/or vertical alignment. Example: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 80 \row - \o \bold Attachment \target Attachment - \o \{ \c scroll \BR + \li \b Attachment \target Attachment + \li \{ \c scroll \BR | \c fixed \}* - \o Scroll or fixed attachment. + \li Scroll or fixed attachment. \row - \o \bold Background \target Background - \o \{ \l{#Brush}{Brush} \BR + \li \b Background \target Background + \li \{ \l{#Brush}{Brush} \BR | \l{#Url}{Url} \BR | \l{#Repeat}{Repeat} \BR | \l{#Alignment}{Alignment} \}* - \o A sequence of \l{#Brush}{Brush}, \l{#Url}{Url}, + \li A sequence of \l{#Brush}{Brush}, \l{#Url}{Url}, \l{#Repeat}{Repeat}, and \l{#Alignment}{Alignment}. \row - \o \bold Boolean \target Boolean - \o 0 | 1 - \o True (\c 1) or false (\c 0). + \li \b Boolean \target Boolean + \li 0 | 1 + \li True (\c 1) or false (\c 0). Example: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 81 \row - \o \bold Border \target Border - \o \{ \l{#Border Style}{Border Style} \BR + \li \b Border \target Border + \li \{ \l{#Border Style}{Border Style} \BR | \l{#Length}{Length} \BR | \l{#Brush}{Brush} \}* - \o Shorthand border property. + \li Shorthand border property. \row - \o \bold{Border Image} \target Border Image - \o \c none \BR + \li \b{Border Image} \target Border Image + \li \c none \BR | \l{Url} \l{Number}\{4\} \BR (\c stretch | \c repeat){0,2} - \o A border image is an image that is composed of nine parts + \li A border image is an image that is composed of nine parts (top left, top center, top right, center left, center, center right, bottom left, bottom center, and bottom right). When a border of a certain size is required, the @@ -2721,8 +2721,8 @@ {CSS3 Draft Specification} for details. \row - \o \bold{Border Style} \target Border Style - \o \c dashed \BR + \li \b{Border Style} \target Border Style + \li \c dashed \BR | \c dot-dash \BR | \c dot-dot-dash \BR | \c dotted \BR @@ -2733,14 +2733,14 @@ | \c ridge \BR | \c solid \BR | \c none - \o Specifies the pattern used to draw a border. + \li Specifies the pattern used to draw a border. See the \l{http://www.w3.org/TR/css3-background/#border-style} {CSS3 Draft Specification} for details. \row - \o \bold{Box Colors} \target Box Colors - \o \l{#Brush}{Brush}\{1,4\} - \o One to four occurrences of \l{#Brush}{Brush}, specifying the top, + \li \b{Box Colors} \target Box Colors + \li \l{#Brush}{Brush}\{1,4\} + \li One to four occurrences of \l{#Brush}{Brush}, specifying the top, right, bottom, and left edges of a box, respectively. If the left color is not specified, it is taken to be the same as the right color. If the bottom color is not @@ -2753,9 +2753,9 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 82 \row - \o \bold{Box Lengths} \target Box Lengths - \o \l{#Length}{Length}\{1,4\} - \o One to four occurrences of \l{#Length}{Length}, specifying the + \li \b{Box Lengths} \target Box Lengths + \li \l{#Length}{Length}\{1,4\} + \li One to four occurrences of \l{#Length}{Length}, specifying the top, right, bottom, and left edges of a box, respectively. If the left length is not specified, it is taken to be the same as the right length. If the bottom @@ -2768,21 +2768,21 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 83 \row - \o \bold{Brush} \target Brush - \o \l{#Color}{Color} \BR + \li \b{Brush} \target Brush + \li \l{#Color}{Color} \BR | \l{Gradient} \BR | \l{PaletteRole} - \o Specifies a Color or a Gradient or an entry in the Palette. + \li Specifies a Color or a Gradient or an entry in the Palette. \row - \o \bold{Color} \target Color - \o \tt{rgb(\e{r}, \e{g}, \e{b})} \BR + \li \b{Color} \target Color + \li \tt{rgb(\e{r}, \e{g}, \e{b})} \BR | \tt{rgba(\e{r}, \e{g}, \e{b}, \e{a})} \BR | \tt{hsv(\e{h}, \e{s}, \e{v})} \BR | \tt{hsva(\e{h}, \e{s}, \e{v}, \e{a})} \BR | \tt{#\e{rrggbb}} \BR | \l{QColor::setNamedColor()}{Color Name} \BR - \o Specifies a color as RGB (red, green, blue) or RGBA + \li Specifies a color as RGB (red, green, blue) or RGBA (red, green, blue, alpha) or HSV (hue, saturation, value) or HSVA (hue, saturation, value, alpha) or a named color. The \c rgb() or \c rgba() syntax can be used with integer values between 0 and 255, or with @@ -2798,45 +2798,45 @@ \l{http://www.w3.org/TR/CSS21/syndata.html#color-units}{here}. \row - \o \bold{Font} \target Font - \o (\l{#Font Style}{Font Style} | \l{#Font Weight}{Font Weight}){0,2} \l{#Font Size}{Font Size} String - \o Shorthand font property. + \li \b{Font} \target Font + \li (\l{#Font Style}{Font Style} | \l{#Font Weight}{Font Weight}){0,2} \l{#Font Size}{Font Size} String + \li Shorthand font property. \row - \o \bold{Font Size} \target Font Size - \o \l{Length} - \o The size of a font. + \li \b{Font Size} \target Font Size + \li \l{Length} + \li The size of a font. \row - \o \bold{Font Style} \target Font Style - \o \c normal \BR + \li \b{Font Style} \target Font Style + \li \c normal \BR | \c italic \BR | \c oblique - \o The style of a font. + \li The style of a font. \row - \o \bold{Font Weight} \target Font Weight - \o \c normal \BR + \li \b{Font Weight} \target Font Weight + \li \c normal \BR | \c bold \BR | \c 100 \BR | \c 200 \BR ... \BR | \c 900 - \o The weight of a font. + \li The weight of a font. \row - \o \bold{Gradient} \target Gradient - \o \c qlineargradient \BR + \li \b{Gradient} \target Gradient + \li \c qlineargradient \BR | \c qradialgradient \BR | \c qconicalgradient - \o Specifies gradient fills. There are three types of gradient fills: + \li Specifies gradient fills. There are three types of gradient fills: \list - \o \e{Linear} gradients interpolate colors between start and + \li \e{Linear} gradients interpolate colors between start and end points. - \o \e{Radial} gradients interpolate colors between a focal + \li \e{Radial} gradients interpolate colors between a focal point and end points on a circle surrounding it. - \o \e{Conical} gradients interpolate colors around a center + \li \e{Conical} gradients interpolate colors around a center point. \endlist @@ -2855,18 +2855,18 @@ \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 85 \row - \o \bold{Icon} \target Icon - \o (\l{#Url}{Url} (\c disabled | \c active | \c normal | \c selected)? + \li \b{Icon} \target Icon + \li (\l{#Url}{Url} (\c disabled | \c active | \c normal | \c selected)? (\c on | \c off)? )* - \o A list of url, QIcon::Mode and QIcon::State. + \li A list of url, QIcon::Mode and QIcon::State. Example: \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 86 \row - \o \bold{Length} \target Length - \o \l{#Number}{Number} (\c px | \c pt | \c em | \c ex)? - \o A number followed by a measurement unit. The CSS standard recommends + \li \b{Length} \target Length + \li \l{#Number}{Number} (\c px | \c pt | \c em | \c ex)? + \li A number followed by a measurement unit. The CSS standard recommends that user agents must \l{http://www.w3.org/TR/CSS21/syndata.html#illegalvalues}{ignore} a declaration with an illegal value. In Qt, it is mandatory to @@ -2875,32 +2875,32 @@ in most contexts. The supported units are: \list - \o \c px: pixels - \o \c pt: the size of one point (i.e., 1/72 of an inch) - \o \c em: the em width of the font (i.e., the width of 'M') - \o \c ex: the ex width of the font (i.e., the height of 'x') + \li \c px: pixels + \li \c pt: the size of one point (i.e., 1/72 of an inch) + \li \c em: the em width of the font (i.e., the width of 'M') + \li \c ex: the ex width of the font (i.e., the height of 'x') \endlist \row - \o \bold{Number} \target Number - \o A decimal integer or a real number - \o Examples: \c 0, \c 18, \c +127, \c -255, \c 12.34, \c -.5, + \li \b{Number} \target Number + \li A decimal integer or a real number + \li Examples: \c 0, \c 18, \c +127, \c -255, \c 12.34, \c -.5, \c 0009. \row - \o \bold{Origin} \target Origin - \o \c margin \BR + \li \b{Origin} \target Origin + \li \c margin \BR | \c border \BR | \c padding \BR | \c content - \o Indicates which of four rectangles to use. + \li Indicates which of four rectangles to use. \list - \o \c margin: The margin rectangle. The margin falls outside the border. - \o \c border: The border rectangle. This is where any border is drawn. - \o \c padding: The padding rectangle. Unlike the margins, + \li \c margin: The margin rectangle. The margin falls outside the border. + \li \c border: The border rectangle. This is where any border is drawn. + \li \c padding: The padding rectangle. Unlike the margins, padding is located inside the border. - \o \c content: The content rectangle. This specifies where + \li \c content: The content rectangle. This specifies where the actual contents go, excluding any padding, border, or margin. \endlist @@ -2908,8 +2908,8 @@ See also \l{The Box Model}. \row - \o \bold{PaletteRole} \target PaletteRole - \o \c alternate-base \BR + \li \b{PaletteRole} \target PaletteRole + \li \c alternate-base \BR | \c base \BR | \c bright-text \BR | \c button \BR @@ -2926,40 +2926,40 @@ | \c text \BR | \c window \BR | \c window-text \BR - \o These values correspond the \l{QPalette::ColorRole}{Color roles} + \li These values correspond the \l{QPalette::ColorRole}{Color roles} in the widget's QPalette. For example, \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 87 \row - \o \bold{Radius} \target Radius - \o \l{#Length}{Length}\{1, 2\} - \o One or two occurrences of \l{#Length}{Length}. If only one length is + \li \b{Radius} \target Radius + \li \l{#Length}{Length}\{1, 2\} + \li One or two occurrences of \l{#Length}{Length}. If only one length is specified, it is used as the radius of the quarter circle defining the corner. If two lengths are specified, the first length is the horizontal radius of a quarter ellipse, whereas the second length is the vertical radius. \row - \o \bold{Repeat} \target Repeat - \o \c repeat-x \BR + \li \b{Repeat} \target Repeat + \li \c repeat-x \BR | \c repeat-y \BR | \c repeat \BR | \c no-repeat - \o A value indicating the nature of repetition. + \li A value indicating the nature of repetition. \list - \o \c repeat-x: Repeat horizontally. - \o \c repeat-y: Repeat vertically. - \o \c repeat: Repeat horizontally and vertically. - \o \c no-repeat: Don't repeat. + \li \c repeat-x: Repeat horizontally. + \li \c repeat-y: Repeat vertically. + \li \c repeat: Repeat horizontally and vertically. + \li \c no-repeat: Don't repeat. \endlist \row - \o \bold{Url} \target Url - \o \tt{url(\e{filename})} - \o \tt{\e{filename}} is the name of a file on the local disk + \li \b{Url} \target Url + \li \tt{url(\e{filename})} + \li \tt{\e{filename}} is the name of a file on the local disk or stored using \l{the Qt Resource System}. Setting an image implicitly sets the width and height of the element. @@ -2971,218 +2971,218 @@ \table 100% \header - \o Pseudo-State - \o Description + \li Pseudo-State + \li Description - \row \o \c :active \target active - \o This state is set when the widget resides in an active window. + \row \li \c :active \target active + \li This state is set when the widget resides in an active window. \row - \o \c :adjoins-item \target adjoins-item-ps - \o This state is set when the \l{#branch-sub}{::branch} of a QTreeView + \li \c :adjoins-item \target adjoins-item-ps + \li This state is set when the \l{#branch-sub}{::branch} of a QTreeView is adjacent to an item. \row - \o \c :alternate \target alternate-ps - \o This state is set for every alternate row whe painting the row of + \li \c :alternate \target alternate-ps + \li This state is set for every alternate row whe painting the row of a QAbstractItemView when QAbstractItemView::alternatingRowColors() is set to true. \row - \o \c :bottom \target bottom-ps - \o The item is positioned at the bottom. For example, a QTabBar + \li \c :bottom \target bottom-ps + \li The item is positioned at the bottom. For example, a QTabBar that has its tabs positioned at the bottom. \row - \o \c :checked \target checked-ps - \o The item is checked. For example, the + \li \c :checked \target checked-ps + \li The item is checked. For example, the \l{QAbstractButton::checked}{checked} state of QAbstractButton. \row - \o \c :closable \target closable-ps - \o The items can be closed. For example, the QDockWidget has the + \li \c :closable \target closable-ps + \li The items can be closed. For example, the QDockWidget has the QDockWidget::DockWidgetClosable feature turned on. \row - \o \c :closed \target closed-ps - \o The item is in the closed state. For example, an non-expanded + \li \c :closed \target closed-ps + \li The item is in the closed state. For example, an non-expanded item in a QTreeView \row - \o \c :default \target default-ps - \o The item is the default. For example, a + \li \c :default \target default-ps + \li The item is the default. For example, a \l{QPushButton::default}{default} QPushButton or a default action in a QMenu. \row - \o \c :disabled \target disabled-ps - \o The item is \l{QWidget::enabled}{disabled}. + \li \c :disabled \target disabled-ps + \li The item is \l{QWidget::enabled}{disabled}. \row - \o \c :editable \target editable-ps - \o The QComboBox is editable. + \li \c :editable \target editable-ps + \li The QComboBox is editable. \row - \o \c :edit-focus \target edit-focus-ps - \o The item has edit focus (See QStyle::State_HasEditFocus). This state + \li \c :edit-focus \target edit-focus-ps + \li The item has edit focus (See QStyle::State_HasEditFocus). This state is available only for Qt Extended applications. \row - \o \c :enabled \target enabled-ps - \o The item is \l{QWidget::enabled}{enabled}. + \li \c :enabled \target enabled-ps + \li The item is \l{QWidget::enabled}{enabled}. \row - \o \c :exclusive \target exclusive-ps - \o The item is part of an exclusive item group. For example, a menu + \li \c :exclusive \target exclusive-ps + \li The item is part of an exclusive item group. For example, a menu item in a exclusive QActionGroup. \row - \o \c :first \target first-ps - \o The item is the first (in a list). For example, the first + \li \c :first \target first-ps + \li The item is the first (in a list). For example, the first tab in a QTabBar. \row - \o \c :flat \target flat-ps - \o The item is flat. For example, a + \li \c :flat \target flat-ps + \li The item is flat. For example, a \l{QPushButton::flat}{flat} QPushButton. \row - \o \c :floatable \target floatable-ps - \o The items can be floated. For example, the QDockWidget has the + \li \c :floatable \target floatable-ps + \li The items can be floated. For example, the QDockWidget has the QDockWidget::DockWidgetFloatable feature turned on. \row - \o \c :focus \target focus-ps - \o The item has \l{QWidget::hasFocus()}{input focus}. + \li \c :focus \target focus-ps + \li The item has \l{QWidget::hasFocus()}{input focus}. \row - \o \c :has-children \target has-children-ps - \o The item has children. For example, an item in a + \li \c :has-children \target has-children-ps + \li The item has children. For example, an item in a QTreeView that has child items. \row - \o \c :has-siblings \target has-siblings-ps - \o The item has siblings. For example, an item in a + \li \c :has-siblings \target has-siblings-ps + \li The item has siblings. For example, an item in a QTreeView that siblings. \row - \o \c :horizontal \target horizontal-ps - \o The item has horizontal orientation + \li \c :horizontal \target horizontal-ps + \li The item has horizontal orientation \row - \o \c :hover \target hover-ps - \o The mouse is hovering over the item. + \li \c :hover \target hover-ps + \li The mouse is hovering over the item. \row - \o \c :indeterminate \target indeterminate-ps - \o The item has indeterminate state. For example, a QCheckBox + \li \c :indeterminate \target indeterminate-ps + \li The item has indeterminate state. For example, a QCheckBox or QRadioButton is \l{Qt::PartiallyChecked}{partially checked}. \row - \o \c :last \target last-ps - \o The item is the last (in a list). For example, the last + \li \c :last \target last-ps + \li The item is the last (in a list). For example, the last tab in a QTabBar. \row - \o \c :left \target left-ps - \o The item is positioned at the left. For example, a QTabBar + \li \c :left \target left-ps + \li The item is positioned at the left. For example, a QTabBar that has its tabs positioned at the left. \row - \o \c :maximized \target maximized-ps - \o The item is maximized. For example, a maximized QMdiSubWindow. + \li \c :maximized \target maximized-ps + \li The item is maximized. For example, a maximized QMdiSubWindow. \row - \o \c :middle \target middle-ps - \o The item is in the middle (in a list). For example, a tab + \li \c :middle \target middle-ps + \li The item is in the middle (in a list). For example, a tab that is not in the beginning or the end in a QTabBar. \row - \o \c :minimized \target minimized-ps - \o The item is minimized. For example, a minimized QMdiSubWindow. + \li \c :minimized \target minimized-ps + \li The item is minimized. For example, a minimized QMdiSubWindow. \row - \o \c :movable \target movable-ps - \o The item can be moved around. For example, the QDockWidget has the + \li \c :movable \target movable-ps + \li The item can be moved around. For example, the QDockWidget has the QDockWidget::DockWidgetMovable feature turned on. \row - \o \c :no-frame \target no-frame-ps - \o The item has no frame. For example, a frameless QSpinBox + \li \c :no-frame \target no-frame-ps + \li The item has no frame. For example, a frameless QSpinBox or QLineEdit. \row - \o \c :non-exclusive \target non-exclusive-ps - \o The item is part of a non-exclusive item group. For example, a menu + \li \c :non-exclusive \target non-exclusive-ps + \li The item is part of a non-exclusive item group. For example, a menu item in a non-exclusive QActionGroup. \row - \o \c :off \target off-ps - \o For items that can be toggled, this applies to items + \li \c :off \target off-ps + \li For items that can be toggled, this applies to items in the "off" state. \row - \o \c :on \target on-ps - \o For items that can be toggled, this applies to widgets + \li \c :on \target on-ps + \li For items that can be toggled, this applies to widgets in the "on" state. \row - \o \c :only-one \target only-one-ps - \o The item is the only one (in a list). For example, a lone tab + \li \c :only-one \target only-one-ps + \li The item is the only one (in a list). For example, a lone tab in a QTabBar. \row - \o \c :open \target open-ps - \o The item is in the open state. For example, an expanded + \li \c :open \target open-ps + \li The item is in the open state. For example, an expanded item in a QTreeView, or a QComboBox or QPushButton with an open menu. \row - \o \c :next-selected \target next-selected-ps - \o The next item (in a list) is selected. For example, the + \li \c :next-selected \target next-selected-ps + \li The next item (in a list) is selected. For example, the selected tab of a QTabBar is next to this item. \row - \o \c :pressed \target pressed-ps - \o The item is being pressed using the mouse. + \li \c :pressed \target pressed-ps + \li The item is being pressed using the mouse. \row - \o \c :previous-selected \target previous-selected-ps - \o The previous item (in a list) is selected. For example, a + \li \c :previous-selected \target previous-selected-ps + \li The previous item (in a list) is selected. For example, a tab in a QTabBar that is next to the selected tab. \row - \o \c :read-only \target read-only-ps - \o The item is marked read only or non-editable. For example, + \li \c :read-only \target read-only-ps + \li The item is marked read only or non-editable. For example, a read only QLineEdit or a non-editable QComboBox. \row - \o \c :right \target right-ps - \o The item is positioned at the right. For example, a QTabBar + \li \c :right \target right-ps + \li The item is positioned at the right. For example, a QTabBar that has its tabs positioned at the right. \row - \o \c :selected \target selected-ps - \o The item is selected. For example, the selected tab in + \li \c :selected \target selected-ps + \li The item is selected. For example, the selected tab in a QTabBar or the selected item in a QMenu. \row - \o \c :top \target top-ps - \o The item is positioned at the top. For example, a QTabBar + \li \c :top \target top-ps + \li The item is positioned at the top. For example, a QTabBar that has its tabs positioned at the top. \row - \o \c :unchecked \target unchecked-ps - \o The item is + \li \c :unchecked \target unchecked-ps + \li The item is \l{QAbstractButton::checked}{unchecked}. \row - \o \c :vertical \target vertical-ps - \o The item has vertical orientation. + \li \c :vertical \target vertical-ps + \li The item has vertical orientation. \row - \o \c :window \target window-ps - \o The widget is a window (i.e top level widget) + \li \c :window \target window-ps + \li The widget is a window (i.e top level widget) \endtable @@ -3193,162 +3193,162 @@ \table 100% \header - \o Sub-Control - \o Description + \li Sub-Control + \li Description \row - \o \c ::add-line \target add-line-sub - \o The button to add a line of a QScrollBar. + \li \c ::add-line \target add-line-sub + \li The button to add a line of a QScrollBar. \row - \o \c ::add-page \target add-page-sub - \o The region between the handle (slider) and the \l{#add-line-sub}{add-line} + \li \c ::add-page \target add-page-sub + \li The region between the handle (slider) and the \l{#add-line-sub}{add-line} of a QScrollBar. \row - \o \c ::branch \target branch-sub - \o The branch indicator of a QTreeView. + \li \c ::branch \target branch-sub + \li The branch indicator of a QTreeView. \row - \o \c ::chunk \target chunk-sub - \o The progress chunk of a QProgressBar. + \li \c ::chunk \target chunk-sub + \li The progress chunk of a QProgressBar. \row - \o \c ::close-button \target close-button-sub - \o The close button of a QDockWidget or tabs of QTabBar + \li \c ::close-button \target close-button-sub + \li The close button of a QDockWidget or tabs of QTabBar \row - \o \c ::corner \target corner-sub - \o The corner between two scrollbars in a QAbstractScrollArea + \li \c ::corner \target corner-sub + \li The corner between two scrollbars in a QAbstractScrollArea \row - \o \c ::down-arrow \target down-arrow-sub - \o The down arrow of a QComboBox, QHeaderView (sort indicator), + \li \c ::down-arrow \target down-arrow-sub + \li The down arrow of a QComboBox, QHeaderView (sort indicator), QScrollBar or QSpinBox. \row - \o \c ::down-button \target down-button-sub - \o The down button of a QScrollBar or a QSpinBox. + \li \c ::down-button \target down-button-sub + \li The down button of a QScrollBar or a QSpinBox. \row - \o \c ::drop-down \target drop-down-sub - \o The drop-down button of a QComboBox. + \li \c ::drop-down \target drop-down-sub + \li The drop-down button of a QComboBox. \row - \o \c ::float-button \target float-button-sub - \o The float button of a QDockWidget + \li \c ::float-button \target float-button-sub + \li The float button of a QDockWidget \row - \o \c ::groove \target groove-sub - \o The groove of a QSlider. + \li \c ::groove \target groove-sub + \li The groove of a QSlider. \row - \o \c ::indicator \target indicator-sub - \o The indicator of a QAbstractItemView, a QCheckBox, a QRadioButton, + \li \c ::indicator \target indicator-sub + \li The indicator of a QAbstractItemView, a QCheckBox, a QRadioButton, a checkable QMenu item or a checkable QGroupBox. \row - \o \c ::handle \target handle-sub - \o The handle (slider) of a QScrollBar, a QSplitter, or a QSlider. + \li \c ::handle \target handle-sub + \li The handle (slider) of a QScrollBar, a QSplitter, or a QSlider. \row - \o \c ::icon \target icon-sub - \o The icon of a QAbstractItemView or a QMenu. + \li \c ::icon \target icon-sub + \li The icon of a QAbstractItemView or a QMenu. \row - \o \c ::item \target item-sub - \o An item of a QAbstractItemView, a QMenuBar, a QMenu, or + \li \c ::item \target item-sub + \li An item of a QAbstractItemView, a QMenuBar, a QMenu, or a QStatusBar. \row - \o \c ::left-arrow \target left-arrow-sub - \o The left arrow of a QScrollBar. + \li \c ::left-arrow \target left-arrow-sub + \li The left arrow of a QScrollBar. \row - \o \c ::left-corner \target left-corner-sub - \o The left corner of a QTabWidget. For example, this control can be + \li \c ::left-corner \target left-corner-sub + \li The left corner of a QTabWidget. For example, this control can be used to control position the left corner widget in a QTabWidget. \row - \o \c ::menu-arrow \target menu-arrow-sub - \o The arrow of a QToolButton with a menu. + \li \c ::menu-arrow \target menu-arrow-sub + \li The arrow of a QToolButton with a menu. \row - \o \c ::menu-button \target menu-button-sub - \o The menu button of a QToolButton. + \li \c ::menu-button \target menu-button-sub + \li The menu button of a QToolButton. \row - \o \c ::menu-indicator \target menu-indicator-sub - \o The menu indicator of a QPushButton. + \li \c ::menu-indicator \target menu-indicator-sub + \li The menu indicator of a QPushButton. \row - \o \c ::right-arrow \target right-arrow-sub - \o The right arrow of a QMenu or a QScrollBar. + \li \c ::right-arrow \target right-arrow-sub + \li The right arrow of a QMenu or a QScrollBar. \row - \o \c ::pane \target pane-sub - \o The pane (frame) of a QTabWidget. + \li \c ::pane \target pane-sub + \li The pane (frame) of a QTabWidget. \row - \o \c ::right-corner \target right-corner-sub - \o The right corner of a QTabWidget. For example, this control can be + \li \c ::right-corner \target right-corner-sub + \li The right corner of a QTabWidget. For example, this control can be used to control the position the right corner widget in a QTabWidget. \row - \o \c ::scroller \target scroller-sub - \o The scroller of a QMenu or QTabBar. + \li \c ::scroller \target scroller-sub + \li The scroller of a QMenu or QTabBar. \row - \o \c ::section \target section-sub - \o The section of a QHeaderView. + \li \c ::section \target section-sub + \li The section of a QHeaderView. \row - \o \c ::separator \target separator-sub - \o The separator of a QMenu or in a QMainWindow. + \li \c ::separator \target separator-sub + \li The separator of a QMenu or in a QMainWindow. \row - \o \c ::sub-line \target sub-line-sub - \o The button to subtract a line of a QScrollBar. + \li \c ::sub-line \target sub-line-sub + \li The button to subtract a line of a QScrollBar. \row - \o \c ::sub-page \target sub-page-sub - \o The region between the handle (slider) and the \l{#sub-line-sub}{sub-line} + \li \c ::sub-page \target sub-page-sub + \li The region between the handle (slider) and the \l{#sub-line-sub}{sub-line} of a QScrollBar. \row - \o \c ::tab \target tab-sub - \o The tab of a QTabBar or QToolBox. + \li \c ::tab \target tab-sub + \li The tab of a QTabBar or QToolBox. \row - \o \c ::tab-bar \target tab-bar-sub - \o The tab bar of a QTabWidget. This subcontrol exists only to + \li \c ::tab-bar \target tab-bar-sub + \li The tab bar of a QTabWidget. This subcontrol exists only to control the position of the QTabBar inside the QTabWidget. To style the tabs using the \l{#tab-sub}{::tab} subcontrol. \row - \o \c ::tear \target tear-sub - \o The tear indicator of a QTabBar. + \li \c ::tear \target tear-sub + \li The tear indicator of a QTabBar. \row - \o \c ::tearoff \target tearoff-sub - \o The tear-off indicator of a QMenu. + \li \c ::tearoff \target tearoff-sub + \li The tear-off indicator of a QMenu. \row - \o \c ::text \target text-ps - \o The text of a QAbstractItemView. + \li \c ::text \target text-ps + \li The text of a QAbstractItemView. \row - \o \c ::title \target title-sub - \o The title of a QGroupBox or a QDockWidget. + \li \c ::title \target title-sub + \li The title of a QGroupBox or a QDockWidget. \row - \o \c ::up-arrow \target up-arrow-sub - \o The up arrow of a QHeaderView (sort indicator), QScrollBar + \li \c ::up-arrow \target up-arrow-sub + \li The up arrow of a QHeaderView (sort indicator), QScrollBar or a QSpinBox. \row - \o \c ::up-button \target up-button-sub - \o The up button of a QSpinBox. + \li \c ::up-button \target up-button-sub + \li The up button of a QSpinBox. \endtable @@ -3441,11 +3441,11 @@ What happened is this: \list - \o We have made a request that cannot be satisfied using the + \li We have made a request that cannot be satisfied using the native styles alone (e.g., the Windows XP theme engine doesn't let us specify the background color of a button). - \o Therefore, the button is rendered using style sheets. - \o We haven't specified any values for + \li Therefore, the button is rendered using style sheets. + \li We haven't specified any values for \l{Qt Style Sheets Reference#border-width-prop}{border-width} and \l{Qt Style Sheets Reference#border-style-prop}{border-style}, so by default we obtain a 0-pixel wide border of style \c none. @@ -3836,18 +3836,18 @@ There are three types of QToolButtons. \list - \i The QToolButton has no menu. In this case, the QToolButton is styled + \li The QToolButton has no menu. In this case, the QToolButton is styled exactly like QPushButton. See \l{#Customizing QPushButton}{Customizing QPushButton} for an example. - \i The QToolButton has a menu and has the QToolButton::popupMode set to + \li The QToolButton has a menu and has the QToolButton::popupMode set to QToolButton::DelayedPopup or QToolButton::InstantPopup. In this case, the QToolButton is styled exactly like a QPushButton with a menu. See \l{#Customizing QPushButton}{Customizing QPushButton} for an example of the usage of the menu-indicator pseudo state. - \i The QToolButton has its QToolButton::popupMode set to + \li The QToolButton has its QToolButton::popupMode set to QToolButton::MenuButtonPopup. In this case, we style it as follows: \endlist @@ -3885,17 +3885,17 @@ \table \row - \o \inlineimage stylesheet-vline.png - \o \inlineimage stylesheet-branch-more.png - \o \inlineimage stylesheet-branch-end.png - \o \inlineimage stylesheet-branch-closed.png - \o \inlineimage stylesheet-branch-open.png - \row - \o vline.png - \o branch-more.png - \o branch-end.png - \o branch-closed.png - \o branch-open.png + \li \inlineimage stylesheet-vline.png + \li \inlineimage stylesheet-branch-more.png + \li \inlineimage stylesheet-branch-end.png + \li \inlineimage stylesheet-branch-closed.png + \li \inlineimage stylesheet-branch-open.png + \row + \li vline.png + \li branch-more.png + \li branch-end.png + \li branch-closed.png + \li branch-open.png \endtable \snippet doc/src/snippets/code/doc_src_stylesheet.qdoc 158 @@ -3948,16 +3948,16 @@ \table \row - \o \inlineimage stylesheet-border-image-stretched.png + \li \inlineimage stylesheet-border-image-stretched.png \row - \o With borders + \li With borders \endtable \table \row - \o \inlineimage stylesheet-border-image-wrong.png + \li \inlineimage stylesheet-border-image-wrong.png \row - \o Without borders + \li Without borders \endtable */ diff --git a/doc/src/widgets/widgets-and-layouts/widgets.qdoc b/doc/src/widgets/widgets-and-layouts/widgets.qdoc index a84f12e70f..e80b0fbec0 100644 --- a/doc/src/widgets/widgets-and-layouts/widgets.qdoc +++ b/doc/src/widgets/widgets-and-layouts/widgets.qdoc @@ -58,8 +58,8 @@ \table \row - \o \image qgridlayout-with-5-children.png - \o \image qformlayout-with-6-children.png + \li \image qgridlayout-with-5-children.png + \li \image qformlayout-with-6-children.png \endtable \l{Qt Designer Manual}{\QD} is a powerful tool for interactively creating and @@ -74,9 +74,9 @@ \table \row - \o \image windowsxp-tabwidget.png - \o \image plastique-tabwidget.png - \o \image macintosh-tabwidget.png + \li \image windowsxp-tabwidget.png + \li \image plastique-tabwidget.png + \li \image macintosh-tabwidget.png \endtable \l{Qt Style Sheets} are a powerful mechanism that allows you to customize the @@ -94,13 +94,13 @@ \table \row - \o \image windows-label.png - \o \image windowsvista-pushbutton.png - \o \image gtk-progressbar.png + \li \image windows-label.png + \li \image windowsvista-pushbutton.png + \li \image gtk-progressbar.png \row - \o \image plastique-combobox.png - \o \image macintosh-radiobutton.png - \o \image cde-lineedit.png + \li \image plastique-combobox.png + \li \image macintosh-radiobutton.png + \li \image cde-lineedit.png \endtable \annotatedlist basicwidgets @@ -112,17 +112,17 @@ \table \row - \o \image windowsxp-treeview.png - \o \image gtk-calendarwidget.png - \o \image qundoview.png + \li \image windowsxp-treeview.png + \li \image gtk-calendarwidget.png + \li \image qundoview.png \endtable \annotatedlist advanced \table \row - \o \image windowsvista-tabwidget.png - \o \image macintosh-groupbox.png + \li \image windowsvista-tabwidget.png + \li \image macintosh-groupbox.png \endtable \section2 Organizer Widgets diff --git a/doc/src/widgets/widgets-tutorial.qdoc b/doc/src/widgets/widgets-tutorial.qdoc index 1d010651e5..735a7ebc54 100644 --- a/doc/src/widgets/widgets-tutorial.qdoc +++ b/doc/src/widgets/widgets-tutorial.qdoc @@ -78,13 +78,13 @@ the \c main() function. \list - \o \l {tutorials/widgets/toplevel} {Creating a window} + \li \l {tutorials/widgets/toplevel} {Creating a window} - \o \l {tutorials/widgets/childwidget} {Creating child widgets} + \li \l {tutorials/widgets/childwidget} {Creating child widgets} - \o \l {tutorials/widgets/windowlayout} {Using layouts} + \li \l {tutorials/widgets/windowlayout} {Using layouts} - \o \l {tutorials/widgets/nestedlayouts} {Nested layouts} + \li \l {tutorials/widgets/nestedlayouts} {Nested layouts} \endlist \section1 Real world widget examples @@ -103,14 +103,14 @@ \list 1 - \o From a command prompt, enter the directory containing the + \li From a command prompt, enter the directory containing the example you have modified. - \o Type \c qmake and press \key{Return}. If this doesn't work, + \li Type \c qmake and press \key{Return}. If this doesn't work, make sure that the executable is on your path, or enter its full location. - \o On Linux/Unix and Mac OS X, type \c make and press + \li On Linux/Unix and Mac OS X, type \c make and press \key{Return}; on Windows with Visual Studio, type \c nmake and press \key{Return}. @@ -137,8 +137,8 @@ \div {class="qt-code"} \table \row - \o \snippet tutorials/widgets/toplevel/main.cpp main program - \o \inlineimage widgets-tutorial-toplevel.png + \li \snippet tutorials/widgets/toplevel/main.cpp main program + \li \inlineimage widgets-tutorial-toplevel.png \endtable \enddiv @@ -159,8 +159,8 @@ \div {class="qt-code"} \table \row - \o \snippet tutorials/widgets/childwidget/main.cpp main program - \o \inlineimage widgets-tutorial-childwidget.png + \li \snippet tutorials/widgets/childwidget/main.cpp main program + \li \inlineimage widgets-tutorial-childwidget.png \endtable \enddiv @@ -181,8 +181,8 @@ \div {class="qt-code"} \table \row - \o \snippet tutorials/widgets/windowlayout/main.cpp main program - \o \inlineimage widgets-tutorial-windowlayout.png + \li \snippet tutorials/widgets/windowlayout/main.cpp main program + \li \inlineimage widgets-tutorial-windowlayout.png \endtable \enddiv @@ -219,9 +219,9 @@ \div {class="qt-code"} \table \row - \o \snippet tutorials/widgets/nestedlayouts/main.cpp first part + \li \snippet tutorials/widgets/nestedlayouts/main.cpp first part \snippet tutorials/widgets/nestedlayouts/main.cpp last part - \o \inlineimage widgets-tutorial-nestedlayouts.png + \li \inlineimage widgets-tutorial-nestedlayouts.png \endtable \enddiv diff --git a/doc/src/widgets/windows-and-dialogs/mainwindow.qdoc b/doc/src/widgets/windows-and-dialogs/mainwindow.qdoc index 1517116c05..3a2efb06a2 100644 --- a/doc/src/widgets/windows-and-dialogs/mainwindow.qdoc +++ b/doc/src/widgets/windows-and-dialogs/mainwindow.qdoc @@ -94,13 +94,13 @@ most common usage transparently. \list - \o \bold{Including the window frame:} + \li \b{Including the window frame:} \l{QWidget::x()}{x()}, \l{QWidget::y()}{y()}, \l{QWidget::frameGeometry()}{frameGeometry()}, \l{QWidget::pos()}{pos()}, and \l{QWidget::move()}{move()}. - \o \bold{Excluding the window frame:} + \li \b{Excluding the window frame:} \l{QWidget::geometry()}{geometry()}, \l{QWidget::width()}{width()}, \l{QWidget::height()}{height()}, @@ -169,17 +169,17 @@ associated user interface components: \list - \o QMainWindow remains the central class around which applications + \li QMainWindow remains the central class around which applications can be built. The interface to this class has been simplified, and much of the functionality previously included in this class is now present in the companion QDockWidget and QToolBar classes. - \o QDockWidget provides a widget that can be used to create + \li QDockWidget provides a widget that can be used to create detachable tool palettes or helper windows. Dock widgets keep track of their own properties, and they can be moved, closed, and floated as external windows. - \o QToolBar provides a generic toolbar widget that can hold a + \li QToolBar provides a generic toolbar widget that can hold a number of different action-related widgets, such as buttons, drop-down menus, comboboxes, and spin boxes. The emphasis on a unified action model in Qt 4 means that toolbars cooperate well diff --git a/src/concurrent/qtconcurrentexception.cpp b/src/concurrent/qtconcurrentexception.cpp index caeaa8d9be..57eb604d39 100644 --- a/src/concurrent/qtconcurrentexception.cpp +++ b/src/concurrent/qtconcurrentexception.cpp @@ -69,10 +69,10 @@ QT_BEGIN_NAMESPACE When using QFuture, transferred exceptions will be thrown when calling the following functions: \list - \o QFuture::waitForFinished() - \o QFuture::result() - \o QFuture::resultAt() - \o QFuture::results() + \li QFuture::waitForFinished() + \li QFuture::result() + \li QFuture::resultAt() + \li QFuture::results() \endlist */ diff --git a/src/concurrent/qtconcurrentrun.cpp b/src/concurrent/qtconcurrentrun.cpp index e51626ed13..656ecf7370 100644 --- a/src/concurrent/qtconcurrentrun.cpp +++ b/src/concurrent/qtconcurrentrun.cpp @@ -121,9 +121,9 @@ this: \list - \o To call a function that takes more than 5 arguments. - \o To simplify calling a function with constant arguments. - \o Changing the order of arguments. + \li To call a function that takes more than 5 arguments. + \li To simplify calling a function with constant arguments. + \li Changing the order of arguments. \endlist See the documentation for the relevant functions for details on how to use diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 35a340836d..2262a3836e 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -98,18 +98,18 @@ QT_BEGIN_NAMESPACE supported QVariant types: \list - \o \l{QMetaType::}{Int} - \o \l{QMetaType::}{Double} - \o \l{QMetaType::}{Float} - \o \l{QMetaType::}{QLine} - \o \l{QMetaType::}{QLineF} - \o \l{QMetaType::}{QPoint} - \o \l{QMetaType::}{QPointF} - \o \l{QMetaType::}{QSize} - \o \l{QMetaType::}{QSizeF} - \o \l{QMetaType::}{QRect} - \o \l{QMetaType::}{QRectF} - \o \l{QMetaType::}{QColor} + \li \l{QMetaType::}{Int} + \li \l{QMetaType::}{Double} + \li \l{QMetaType::}{Float} + \li \l{QMetaType::}{QLine} + \li \l{QMetaType::}{QLineF} + \li \l{QMetaType::}{QPoint} + \li \l{QMetaType::}{QPointF} + \li \l{QMetaType::}{QSize} + \li \l{QMetaType::}{QSizeF} + \li \l{QMetaType::}{QRect} + \li \l{QMetaType::}{QRectF} + \li \l{QMetaType::}{QColor} \endlist If you need to interpolate other variant types, including custom diff --git a/src/corelib/codecs/codecs.qdoc b/src/corelib/codecs/codecs.qdoc index 2127a0a4cf..669072f789 100644 --- a/src/corelib/codecs/codecs.qdoc +++ b/src/corelib/codecs/codecs.qdoc @@ -77,9 +77,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -126,9 +126,9 @@ Currently, the Big5-HKSCS tables are generated from the following sources, and with the Euro character added: \list 1 - \o \l{http://www.microsoft.com/typography/unicode/950.txt} - \o \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5-iso.txt} - \o \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5cmp.txt} + \li \l{http://www.microsoft.com/typography/unicode/950.txt} + \li \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5-iso.txt} + \li \l{http://www.info.gov.hk/digital21/chi/hkscs/download/big5cmp.txt} \endlist There may be more fine-tuning to the QBig5hkscsCodec to maximize its @@ -147,9 +147,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -195,9 +195,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -238,9 +238,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -282,9 +282,9 @@ Some must-read documents are: \list - \o \l{ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/pdf/GB18030_Summary.pdf} - \o \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/source/gb18030/gb18030.html} - \o \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/data/xml/gb-18030-2000.xml} + \li \l{ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/pdf/GB18030_Summary.pdf} + \li \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/source/gb18030/gb18030.html} + \li \l{http://oss.software.ibm.com/cvs/icu/~checkout~/charset/data/xml/gb-18030-2000.xml} \endlist The GBK codec was contributed to Qt by @@ -316,9 +316,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -354,30 +354,30 @@ \list - \o "unicode-0.9" or "unicode-0201" for Unicode style. This assumes + \li "unicode-0.9" or "unicode-0201" for Unicode style. This assumes JISX0201 for 0x00-0x7f. (0.9 is a table version of jisx02xx mapping used for Unicode 1.1.) - \o "unicode-ascii" This assumes US-ASCII for 0x00-0x7f; some + \li "unicode-ascii" This assumes US-ASCII for 0x00-0x7f; some chars (JISX0208 0x2140 and JISX0212 0x2237) are different from Unicode 1.1 to avoid conflict. - \o "open-19970715-0201" ("open-0201" for convenience) or + \li "open-19970715-0201" ("open-0201" for convenience) or "jisx0221-1995" for JISX0221-JISX0201 style. JIS X 0221 is JIS version of Unicode, but a few chars (0x5c, 0x7e, 0x2140, 0x216f, 0x2131) are different from Unicode 1.1. This is used when 0x5c is treated as YEN SIGN. - \o "open-19970715-ascii" ("open-ascii" for convenience) for + \li "open-19970715-ascii" ("open-ascii" for convenience) for JISX0221-ASCII style. This is used when 0x5c is treated as REVERSE SOLIDUS. - \o "open-19970715-ms" ("open-ms" for convenience) or "cp932" for + \li "open-19970715-ms" ("open-ms" for convenience) or "cp932" for Microsoft Windows style. Windows Code Page 932. Some chars (0x2140, 0x2141, 0x2142, 0x215d, 0x2171, 0x2172) are different from Unicode 1.1. - \o "jdk1.1.7" for Sun's JDK style. Same as Unicode 1.1, except that + \li "jdk1.1.7" for Sun's JDK style. Same as Unicode 1.1, except that JIS 0x2140 is mapped to UFF3C. Either ASCII or JISX0201 can be used for 0x00-0x7f. @@ -405,9 +405,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -454,9 +454,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist @@ -510,9 +510,9 @@ are met: \list 1 - \o Redistributions of source code must retain the above copyright + \li Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - \o Redistributions in binary form must reproduce the above copyright + \li Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \endlist diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 68866b9000..4cfdfe5966 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -789,38 +789,38 @@ QTextCodec::ConverterState::~ConverterState() The supported encodings are: \list - \o Apple Roman - \o \l{Big5 Text Codec}{Big5} - \o \l{Big5-HKSCS Text Codec}{Big5-HKSCS} - \o CP949 - \o \l{EUC-JP Text Codec}{EUC-JP} - \o \l{EUC-KR Text Codec}{EUC-KR} - \o \l{GBK Text Codec}{GB18030-0} - \o IBM 850 - \o IBM 866 - \o IBM 874 - \o \l{ISO 2022-JP (JIS) Text Codec}{ISO 2022-JP} - \o ISO 8859-1 to 10 - \o ISO 8859-13 to 16 - \o Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml - \o JIS X 0201 - \o JIS X 0208 - \o KOI8-R - \o KOI8-U - \o MuleLao-1 - \o ROMAN8 - \o \l{Shift-JIS Text Codec}{Shift-JIS} - \o TIS-620 - \o \l{TSCII Text Codec}{TSCII} - \o UTF-8 - \o UTF-16 - \o UTF-16BE - \o UTF-16LE - \o UTF-32 - \o UTF-32BE - \o UTF-32LE - \o Windows-1250 to 1258 - \o WINSAMI2 + \li Apple Roman + \li \l{Big5 Text Codec}{Big5} + \li \l{Big5-HKSCS Text Codec}{Big5-HKSCS} + \li CP949 + \li \l{EUC-JP Text Codec}{EUC-JP} + \li \l{EUC-KR Text Codec}{EUC-KR} + \li \l{GBK Text Codec}{GB18030-0} + \li IBM 850 + \li IBM 866 + \li IBM 874 + \li \l{ISO 2022-JP (JIS) Text Codec}{ISO 2022-JP} + \li ISO 8859-1 to 10 + \li ISO 8859-13 to 16 + \li Iscii-Bng, Dev, Gjr, Knd, Mlm, Ori, Pnj, Tlg, and Tml + \li JIS X 0201 + \li JIS X 0208 + \li KOI8-R + \li KOI8-U + \li MuleLao-1 + \li ROMAN8 + \li \l{Shift-JIS Text Codec}{Shift-JIS} + \li TIS-620 + \li \l{TSCII Text Codec}{TSCII} + \li UTF-8 + \li UTF-16 + \li UTF-16BE + \li UTF-16LE + \li UTF-32 + \li UTF-32BE + \li UTF-32LE + \li Windows-1250 to 1258 + \li WINSAMI2 \endlist QTextCodecs can be used as follows to convert some locally encoded @@ -871,29 +871,29 @@ QTextCodec::ConverterState::~ConverterState() QTextCodec and implement the functions listed in the table below. \table - \header \o Function \o Description + \header \li Function \li Description - \row \o name() - \o Returns the official name for the encoding. If the + \row \li name() + \li Returns the official name for the encoding. If the encoding is listed in the \l{IANA character-sets encoding file}, the name should be the preferred MIME name for the encoding. - \row \o aliases() - \o Returns a list of alternative names for the encoding. + \row \li aliases() + \li Returns a list of alternative names for the encoding. QTextCodec provides a default implementation that returns an empty list. For example, "ISO-8859-1" has "latin1", "CP819", "IBM819", and "iso-ir-100" as aliases. - \row \o mibEnum() - \o Return the MIB enum for the encoding if it is listed in + \row \li mibEnum() + \li Return the MIB enum for the encoding if it is listed in the \l{IANA character-sets encoding file}. - \row \o convertToUnicode() - \o Converts an 8-bit character string to Unicode. + \row \li convertToUnicode() + \li Converts an 8-bit character string to Unicode. - \row \o convertFromUnicode() - \o Converts a Unicode string to an 8-bit character string. + \row \li convertFromUnicode() + \li Converts a Unicode string to an 8-bit character string. \endtable \sa QTextStream, QTextDecoder, QTextEncoder, {Codecs Example} diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6257376b62..a30250df81 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -892,13 +892,13 @@ bool qSharedBuild() \brief The QSysInfo class provides information about the system. \list - \o \l WordSize specifies the size of a pointer for the platform + \li \l WordSize specifies the size of a pointer for the platform on which the application is compiled. - \o \l ByteOrder specifies whether the platform is big-endian or + \li \l ByteOrder specifies whether the platform is big-endian or little-endian. - \o \l WindowsVersion specifies the version of the Windows operating + \li \l WindowsVersion specifies the version of the Windows operating system on which the application is run (Windows only) - \o \l MacintoshVersion specifies the version of the Macintosh + \li \l MacintoshVersion specifies the version of the Macintosh operating system on which the application is run (Mac only). \endlist @@ -2462,12 +2462,12 @@ int qrand() \a Flags can be one of the following: \list - \o \c Q_PRIMITIVE_TYPE specifies that \a Type is a POD (plain old + \li \c Q_PRIMITIVE_TYPE specifies that \a Type is a POD (plain old data) type with no constructor or destructor. - \o \c Q_MOVABLE_TYPE specifies that \a Type has a constructor + \li \c Q_MOVABLE_TYPE specifies that \a Type has a constructor and/or a destructor but can be moved in memory using \c memcpy(). - \o \c Q_COMPLEX_TYPE (the default) specifies that \a Type has + \li \c Q_COMPLEX_TYPE (the default) specifies that \a Type has constructors and/or a destructor and that it may not be moved in memory. \endlist diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index badccc947d..8cbd4528dc 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -309,7 +309,7 @@ QDebug QMessageLogger::critical() message handler has been installed, the message is printed to stderr. Under Windows, the message is sent to the debugger. - If you are using the \bold{default message handler} this function will + If you are using the \b{default message handler} this function will abort on Unix systems to create a core dump. On Windows, for debug builds, this function will report a _CRT_ERROR enabling you to connect a debugger to the application. diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 895feb7f53..7d5eec4271 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -266,7 +266,7 @@ This enum provides shorter names for the keyboard modifier keys supported by Qt. - \bold{Note:} On Mac OS X, the \c CTRL value corresponds to + \b{Note:} On Mac OS X, the \c CTRL value corresponds to the Command keys on the Macintosh keyboard, and the \c META value corresponds to the Control keys. @@ -319,21 +319,21 @@ \table \row - \o \inlineimage qpen-solid.png - \o \inlineimage qpen-dash.png - \o \inlineimage qpen-dot.png + \li \inlineimage qpen-solid.png + \li \inlineimage qpen-dash.png + \li \inlineimage qpen-dot.png \row - \o Qt::SolidLine - \o Qt::DashLine - \o Qt::DotLine + \li Qt::SolidLine + \li Qt::DashLine + \li Qt::DotLine \row - \o \inlineimage qpen-dashdot.png - \o \inlineimage qpen-dashdotdot.png - \o \inlineimage qpen-custom.png + \li \inlineimage qpen-dashdot.png + \li \inlineimage qpen-dashdotdot.png + \li \inlineimage qpen-custom.png \row - \o Qt::DashDotLine - \o Qt::DashDotDotLine - \o Qt::CustomDashLine + \li Qt::DashDotLine + \li Qt::DashDotDotLine + \li Qt::CustomDashLine \endtable \value NoPen no line at all. For example, QPainter::drawRect() @@ -360,13 +360,13 @@ \table \row - \o \inlineimage qpen-square.png - \o \inlineimage qpen-flat.png - \o \inlineimage qpen-roundcap.png + \li \inlineimage qpen-square.png + \li \inlineimage qpen-flat.png + \li \inlineimage qpen-roundcap.png \row - \o Qt::SquareCap - \o Qt::FlatCap - \o Qt::RoundCap + \li Qt::SquareCap + \li Qt::FlatCap + \li Qt::RoundCap \endtable \value FlatCap a square line end that does not cover the end @@ -388,13 +388,13 @@ \table \row - \o \inlineimage qpen-bevel.png - \o \inlineimage qpen-miter.png - \o \inlineimage qpen-roundjoin.png + \li \inlineimage qpen-bevel.png + \li \inlineimage qpen-miter.png + \li \inlineimage qpen-roundjoin.png \row - \o Qt::BevelJoin - \o Qt::MiterJoin - \o Qt::RoundJoin + \li Qt::BevelJoin + \li Qt::MiterJoin + \li Qt::RoundJoin \endtable \value MiterJoin The outer edges of the lines are extended to @@ -968,7 +968,7 @@ \value WA_NoSystemBackground Indicates that the widget has no background, i.e. when the widget receives paint events, the background is not automatically repainted. \note Unlike WA_OpaquePaintEvent, newly exposed - areas are \bold never filled with the background (e.g., after showing a + areas are \b never filled with the background (e.g., after showing a window for the first time the user can see "through" it until the application processes the paint events). This flag is set or cleared by the widget's author. diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index f3fe91427a..1fe2a793a6 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -184,7 +184,7 @@ QT_BEGIN_NAMESPACE \endcode To see if your favorite Qt class has similar stream operators - defined, check the \bold {Related Non-Members} section of the + defined, check the \b {Related Non-Members} section of the class's documentation page. \sa QTextStream QVariant @@ -571,19 +571,19 @@ void QDataStream::setByteOrder(ByteOrder bo) serialization format used by QDataStream. \table - \header \i Qt Version \i QDataStream Version - \row \i Qt 4.6 \i 12 - \row \i Qt 4.5 \i 11 - \row \i Qt 4.4 \i 10 - \row \i Qt 4.3 \i 9 - \row \i Qt 4.2 \i 8 - \row \i Qt 4.0, 4.1 \i 7 - \row \i Qt 3.3 \i 6 - \row \i Qt 3.1, 3.2 \i 5 - \row \i Qt 3.0 \i 4 - \row \i Qt 2.1, 2.2, 2.3 \i 3 - \row \i Qt 2.0 \i 2 - \row \i Qt 1.x \i 1 + \header \li Qt Version \li QDataStream Version + \row \li Qt 4.6 \li 12 + \row \li Qt 4.5 \li 11 + \row \li Qt 4.4 \li 10 + \row \li Qt 4.3 \li 9 + \row \li Qt 4.2 \li 8 + \row \li Qt 4.0, 4.1 \li 7 + \row \li Qt 3.3 \li 6 + \row \li Qt 3.1, 3.2 \li 5 + \row \li Qt 3.0 \li 4 + \row \li Qt 2.1, 2.2, 2.3 \li 3 + \row \li Qt 2.0 \li 2 + \row \li Qt 1.x \li 1 \endtable The \l Version enum provides symbolic constants for the different diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index afd402d019..1dedc7c5c8 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -451,11 +451,11 @@ inline void QDirPrivate::initFileEngine() for these that return strings: \table - \header \o QDir \o QString \o Return Value - \row \o current() \o currentPath() \o The application's working directory - \row \o home() \o homePath() \o The user's home directory - \row \o root() \o rootPath() \o The root directory - \row \o temp() \o tempPath() \o The system's temporary directory + \header \li QDir \li QString \li Return Value + \row \li current() \li currentPath() \li The application's working directory + \row \li home() \li homePath() \li The user's home directory + \row \li root() \li rootPath() \li The root directory + \row \li temp() \li tempPath() \li The system's temporary directory \endtable The setCurrent() static function can also be used to set the application's @@ -1878,13 +1878,13 @@ QString QDir::currentPath() the given order) until an existing and available path is found: \list 1 - \o The path specified by the \c USERPROFILE environment variable. - \o The path formed by concatenating the \c HOMEDRIVE and \c HOMEPATH + \li The path specified by the \c USERPROFILE environment variable. + \li The path formed by concatenating the \c HOMEDRIVE and \c HOMEPATH environment variables. - \o The path specified by the \c HOME environment variable. - \o The path returned by the rootPath() function (which uses the \c SystemDrive + \li The path specified by the \c HOME environment variable. + \li The path returned by the rootPath() function (which uses the \c SystemDrive environment variable) - \o The \c{C:/} directory. + \li The \c{C:/} directory. \endlist Under non-Windows operating systems the \c HOME environment diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index fc0c90cf69..6640dca70b 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1034,13 +1034,13 @@ bool QFile::open(OpenMode mode) then calling close() closes the adopted handle. Otherwise, close() does not actually close the file, but only flushes it. - \bold{Warning:} + \b{Warning:} \list 1 - \o If \a fh does not refer to a regular file, e.g., it is \c stdin, + \li If \a fh does not refer to a regular file, e.g., it is \c stdin, \c stdout, or \c stderr, you may not be able to seek(). size() returns \c 0 in those cases. See QIODevice::isSequential() for more information. - \o Since this function opens the file without specifying the file name, + \li Since this function opens the file without specifying the file name, you cannot use this QFile with a QFileInfo. \endlist @@ -1048,7 +1048,7 @@ bool QFile::open(OpenMode mode) \sa close(), {qmake Variable Reference#CONFIG}{qmake Variable Reference} - \bold{Note for the Windows Platform} + \b{Note for the Windows Platform} \a fh must be opened in binary mode (i.e., the mode string must contain 'b', as in "rb" or "wb") when accessing files and other random-access diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index a7fb0fb6c7..044c71d00a 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -812,7 +812,7 @@ QString QFileInfo::suffix() const /*! Returns the path of the object's parent directory as a QDir object. - \bold{Note:} The QDir returned always corresponds to the object's + \b{Note:} The QDir returned always corresponds to the object's parent directory, even if the QFileInfo represents a directory. For each of the following, dir() returns a QDir for @@ -901,7 +901,7 @@ bool QFileInfo::isExecutable() const /*! Returns true if this is a `hidden' file; otherwise returns false. - \bold{Note:} This function returns true for the special entries + \b{Note:} This function returns true for the special entries "." and ".." on Unix, even though QDir::entryList threats them as shown. */ bool QFileInfo::isHidden() const @@ -923,7 +923,7 @@ bool QFileInfo::isHidden() const Returns false if the file is otherwise supported by a virtual file system inside Qt, such as \l{the Qt Resource System}. - \bold{Note:} Native paths may still require conversion of path separators + \b{Note:} Native paths may still require conversion of path separators and character encoding, depending on platform and input requirements of the native API. diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 3d9391ebaa..1cdfc61627 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -163,12 +163,12 @@ QIODevicePrivate::~QIODevicePrivate() random-access devices and sequential devices. \list - \o Random-access devices support seeking to arbitrary + \li Random-access devices support seeking to arbitrary positions using seek(). The current position in the file is available by calling pos(). QFile and QBuffer are examples of random-access devices. - \o Sequential devices don't support seeking to arbitrary + \li Sequential devices don't support seeking to arbitrary positions. The data must be read in one pass. The functions pos() and size() don't work for sequential devices. QTcpSocket and QProcess are examples of sequential devices. @@ -199,14 +199,14 @@ QIODevicePrivate::~QIODevicePrivate() a separate thread: \list - \o waitForReadyRead() - This function suspends operation in the + \li waitForReadyRead() - This function suspends operation in the calling thread until new data is available for reading. - \o waitForBytesWritten() - This function suspends operation in the + \li waitForBytesWritten() - This function suspends operation in the calling thread until one payload of data has been written to the device. - \o waitFor....() - Subclasses of QIODevice implement blocking + \li waitFor....() - Subclasses of QIODevice implement blocking functions for device-specific operations. For example, QProcess has a function called waitForStarted() which suspends operation in the calling thread until the process has started. @@ -1038,9 +1038,9 @@ QByteArray QIODevice::readAll() Data is read until either of the following conditions are met: \list - \o The first '\n' character is read. - \o \a maxSize - 1 bytes are read. - \o The end of the device data is detected. + \li The first '\n' character is read. + \li \a maxSize - 1 bytes are read. + \li The end of the device data is detected. \endlist For example, the following code reads a line of characters from a diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 7a81313fa0..640704ec86 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -532,15 +532,15 @@ void QProcessPrivate::Channel::clear() certain signals are emitted: \list - \o waitForStarted() blocks until the process has started. + \li waitForStarted() blocks until the process has started. - \o waitForReadyRead() blocks until new data is + \li waitForReadyRead() blocks until new data is available for reading on the current read channel. - \o waitForBytesWritten() blocks until one payload of + \li waitForBytesWritten() blocks until one payload of data has been written to the process. - \o waitForFinished() blocks until the process has finished. + \li waitForFinished() blocks until the process has finished. \endlist Calling these functions from the main thread (the thread that @@ -1910,7 +1910,7 @@ QByteArray QProcess::readAllStandardError() \note No further splitting of the arguments is performed. - \bold{Windows:} Arguments that contain spaces are wrapped in quotes. + \b{Windows:} Arguments that contain spaces are wrapped in quotes. \sa pid(), started(), waitForStarted() */ @@ -2149,10 +2149,10 @@ int QProcess::execute(const QString &program) Note that arguments that contain spaces are not passed to the process as separate arguments. - \bold{Unix:} The started process will run in its own session and act + \b{Unix:} The started process will run in its own session and act like a daemon. - \bold{Windows:} Arguments that contain spaces are wrapped in quotes. + \b{Windows:} Arguments that contain spaces are wrapped in quotes. The started process will run as a regular standalone process. The process will be started in the directory \a workingDirectory. @@ -2183,10 +2183,10 @@ bool QProcess::startDetached(const QString &program, \note Arguments that contain spaces are not passed to the process as separate arguments. - \bold{Unix:} The started process will run in its own session and act + \b{Unix:} The started process will run in its own session and act like a daemon. - \bold{Windows:} Arguments that contain spaces are wrapped in quotes. + \b{Windows:} Arguments that contain spaces are wrapped in quotes. The started process will run as a regular standalone process. */ bool QProcess::startDetached(const QString &program, diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 2021c42c4d..e4d90e000a 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -2112,15 +2112,15 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, avoid portability problems, follow these simple rules: \list 1 - \o Always refer to the same key using the same case. For example, + \li Always refer to the same key using the same case. For example, if you refer to a key as "text fonts" in one place in your code, don't refer to it as "Text Fonts" somewhere else. - \o Avoid key names that are identical except for the case. For + \li Avoid key names that are identical except for the case. For example, if you have a key called "MainWindow", don't try to save another key as "mainwindow". - \o Do not use slashes ('/' and '\\') in section or key names; the + \li Do not use slashes ('/' and '\\') in section or key names; the backslash character is used to separate sub keys (see below). On windows '\\' are converted by QSettings to '/', which makes them identical. @@ -2156,10 +2156,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, that order: \list 1 - \o a user-specific location for the Star Runner application - \o a user-specific location for all applications by MySoft - \o a system-wide location for the Star Runner application - \o a system-wide location for all applications by MySoft + \li a user-specific location for the Star Runner application + \li a user-specific location for all applications by MySoft + \li a system-wide location for the Star Runner application + \li a system-wide location for all applications by MySoft \endlist (See \l{Platform-Specific Notes} below for information on what @@ -2184,17 +2184,17 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \snippet doc/src/snippets/settings/settings.cpp 14 The table below summarizes which QSettings objects access - which location. "\bold{X}" means that the location is the main + which location. "\b{X}" means that the location is the main location associated to the QSettings object and is used both for reading and for writing; "o" means that the location is used as a fallback when reading. \table - \header \o Locations \o \c{obj1} \o \c{obj2} \o \c{obj3} \o \c{obj4} - \row \o 1. User, Application \o \bold{X} \o \o \o - \row \o 2. User, Organization \o o \o \bold{X} \o \o - \row \o 3. System, Application \o o \o \o \bold{X} \o - \row \o 4. System, Organization \o o \o o \o o \o \bold{X} + \header \li Locations \li \c{obj1} \li \c{obj2} \li \c{obj3} \li \c{obj4} + \row \li 1. User, Application \li \b{X} \li \li \li + \row \li 2. User, Organization \li o \li \b{X} \li \li + \row \li 3. System, Application \li o \li \li \b{X} \li + \row \li 4. System, Organization \li o \li o \li o \li \b{X} \endtable The beauty of this mechanism is that it works on all platforms @@ -2276,30 +2276,30 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, following files are used by default: \list 1 - \o \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf}) - \o \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf}) - \o \c{/etc/xdg/MySoft/Star Runner.conf} - \o \c{/etc/xdg/MySoft.conf} + \li \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf}) + \li \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf}) + \li \c{/etc/xdg/MySoft/Star Runner.conf} + \li \c{/etc/xdg/MySoft.conf} \endlist On Mac OS X versions 10.2 and 10.3, these files are used by default: \list 1 - \o \c{$HOME/Library/Preferences/com.MySoft.Star Runner.plist} - \o \c{$HOME/Library/Preferences/com.MySoft.plist} - \o \c{/Library/Preferences/com.MySoft.Star Runner.plist} - \o \c{/Library/Preferences/com.MySoft.plist} + \li \c{$HOME/Library/Preferences/com.MySoft.Star Runner.plist} + \li \c{$HOME/Library/Preferences/com.MySoft.plist} + \li \c{/Library/Preferences/com.MySoft.Star Runner.plist} + \li \c{/Library/Preferences/com.MySoft.plist} \endlist On Windows, NativeFormat settings are stored in the following registry paths: \list 1 - \o \c{HKEY_CURRENT_USER\Software\MySoft\Star Runner} - \o \c{HKEY_CURRENT_USER\Software\MySoft} - \o \c{HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner} - \o \c{HKEY_LOCAL_MACHINE\Software\MySoft} + \li \c{HKEY_CURRENT_USER\Software\MySoft\Star Runner} + \li \c{HKEY_CURRENT_USER\Software\MySoft} + \li \c{HKEY_LOCAL_MACHINE\Software\MySoft\Star Runner} + \li \c{HKEY_LOCAL_MACHINE\Software\MySoft} \endlist \note On Windows, for 32-bit programs running in WOW64 mode, settings are @@ -2310,19 +2310,19 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, used on Unix and Mac OS X: \list 1 - \o \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini}) - \o \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini}) - \o \c{/etc/xdg/MySoft/Star Runner.ini} - \o \c{/etc/xdg/MySoft.ini} + \li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini}) + \li \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini}) + \li \c{/etc/xdg/MySoft/Star Runner.ini} + \li \c{/etc/xdg/MySoft.ini} \endlist On Windows, the following files are used: \list 1 - \o \c{%APPDATA%\MySoft\Star Runner.ini} - \o \c{%APPDATA%\MySoft.ini} - \o \c{%COMMON_APPDATA%\MySoft\Star Runner.ini} - \o \c{%COMMON_APPDATA%\MySoft.ini} + \li \c{%APPDATA%\MySoft\Star Runner.ini} + \li \c{%APPDATA%\MySoft.ini} + \li \c{%COMMON_APPDATA%\MySoft\Star Runner.ini} + \li \c{%COMMON_APPDATA%\MySoft.ini} \endlist The \c %APPDATA% path is usually \tt{C:\\Documents and @@ -2395,20 +2395,20 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, application: \list - \o The Windows system registry has the following limitations: A + \li The Windows system registry has the following limitations: A subkey may not exceed 255 characters, an entry's value may not exceed 16,383 characters, and all the values of a key may not exceed 65,535 characters. One way to work around these limitations is to store the settings using the IniFormat instead of the NativeFormat. - \o On Mac OS X, allKeys() will return some extra keys for global + \li On Mac OS X, allKeys() will return some extra keys for global settings that apply to all applications. These keys can be read using value() but cannot be changed, only shadowed. Calling setFallbacksEnabled(false) will hide these global settings. - \o On Mac OS X, the CFPreferences API used by QSettings expects + \li On Mac OS X, the CFPreferences API used by QSettings expects Internet domain names rather than organization names. To provide a uniform API, QSettings derives a fake domain name from the organization name (unless the organization name @@ -2425,7 +2425,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \snippet doc/src/snippets/code/src_corelib_io_qsettings.cpp 7 - \o On Unix and Mac OS X systems, the advisory file locking is disabled + \li On Unix and Mac OS X systems, the advisory file locking is disabled if NFS (or AutoFS or CacheFS) is detected to work around a bug in the NFS fcntl() implementation, which hangs forever if statd or lockd aren't running. Also, the locking isn't performed when accessing \c .plist @@ -2485,7 +2485,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, follow what Microsoft does, with the following exceptions: \list - \o If you store types that QVariant can't convert to QString + \li If you store types that QVariant can't convert to QString (e.g., QPoint, QRect, and QSize), Qt uses an \c{@}-based syntax to encode the type. For example: @@ -2496,7 +2496,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, followed by a Qt type (\c Point, \c Rect, \c Size, etc.) is treated as a normal character. - \o Although backslash is a special character in INI files, most + \li Although backslash is a special character in INI files, most Windows applications don't escape backslashes (\c{\}) in file paths: @@ -2505,7 +2505,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, QSettings always treats backslash as a special character and provides no API for reading or writing such entries. - \o The INI file format has severe restrictions on the syntax of + \li The INI file format has severe restrictions on the syntax of a key. Qt works around this by using \c % as an escape character in keys. In addition, if you save a top-level setting (a key with no slashes in it, e.g., "someKey"), it @@ -2514,7 +2514,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, such as "General/someKey", the key will be located in the "%General" section, \e not in the "General" section. - \o Following the philosophy that we should be liberal in what + \li Following the philosophy that we should be liberal in what we accept and conservative in what we generate, QSettings will accept Latin-1 encoded INI files, but generate pure ASCII files, where non-ASCII values are encoded using standard @@ -2632,10 +2632,10 @@ QSettings::QSettings(Format format, Scope scope, const QString &organization, be aware of the following limitations: \list - \o QSettings provides no way of reading INI "path" entries, i.e., entries + \li QSettings provides no way of reading INI "path" entries, i.e., entries with unescaped slash characters. (This is because these entries are ambiguous and cannot be resolved automatically.) - \o In INI files, QSettings uses the \c @ character as a metacharacter in some + \li In INI files, QSettings uses the \c @ character as a metacharacter in some contexts, to encode Qt-specific data types (e.g., \c @Rect), and might therefore misinterpret it when it occurs in pure INI files. \endlist @@ -2933,9 +2933,9 @@ QSettings::Status QSettings::status() const This will set the value of three settings: \list - \o \c mainwindow/size - \o \c mainwindow/fullScreen - \o \c outputpanel/visible + \li \c mainwindow/size + \li \c mainwindow/fullScreen + \li \c outputpanel/visible \endlist Call endGroup() to reset the current group to what it was before @@ -3021,14 +3021,14 @@ int QSettings::beginReadArray(const QString &prefix) The generated keys will have the form \list - \o \c logins/size - \o \c logins/1/userName - \o \c logins/1/password - \o \c logins/2/userName - \o \c logins/2/password - \o \c logins/3/userName - \o \c logins/3/password - \o ... + \li \c logins/size + \li \c logins/1/userName + \li \c logins/1/password + \li \c logins/2/userName + \li \c logins/2/password + \li \c logins/3/userName + \li \c logins/3/password + \li ... \endlist To read back an array, use beginReadArray(). @@ -3412,15 +3412,15 @@ void QSettings::setUserIniPath(const QString &dir) The table below summarizes the default values: \table - \header \o Platform \o Format \o Scope \o Path - \row \o{1,2} Windows \o{1,2} IniFormat \o UserScope \o \c %APPDATA% - \row \o SystemScope \o \c %COMMON_APPDATA% - \row \o{1,2} Unix \o{1,2} NativeFormat, IniFormat \o UserScope \o \c $HOME/.config - \row \o SystemScope \o \c /etc/xdg - \row \o{1,2} Qt for Embedded Linux \o{1,2} NativeFormat, IniFormat \o UserScope \o \c $HOME/Settings - \row \o SystemScope \o \c /etc/xdg - \row \o{1,2} Mac OS X \o{1,2} IniFormat \o UserScope \o \c $HOME/.config - \row \o SystemScope \o \c /etc/xdg + \header \li Platform \li Format \li Scope \li Path + \row \li{1,2} Windows \li{1,2} IniFormat \li UserScope \li \c %APPDATA% + \row \li SystemScope \li \c %COMMON_APPDATA% + \row \li{1,2} Unix \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/.config + \row \li SystemScope \li \c /etc/xdg + \row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings + \row \li SystemScope \li \c /etc/xdg + \row \li{1,2} Mac OS X \li{1,2} IniFormat \li UserScope \li \c $HOME/.config + \row \li SystemScope \li \c /etc/xdg \endtable The default UserScope paths on Unix and Mac OS X (\c diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index dd0ab85119..cb703df8c6 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -90,13 +90,13 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; \list - \o Chunk by chunk, by calling readLine() or readAll(). + \li Chunk by chunk, by calling readLine() or readAll(). - \o Word by word. QTextStream supports streaming into QStrings, + \li Word by word. QTextStream supports streaming into QStrings, QByteArrays and char* buffers. Words are delimited by space, and leading white space is automatically skipped. - \o Character by character, by streaming into QChar or char types. + \li Character by character, by streaming into QChar or char types. This method is often used for convenient input handling when parsing files, independent of character encoding and end-of-line semantics. To skip white space, call skipWhiteSpace(). @@ -134,31 +134,31 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; defines several global manipulator functions: \table - \header \o Manipulator \o Description - \row \o \c bin \o Same as setIntegerBase(2). - \row \o \c oct \o Same as setIntegerBase(8). - \row \o \c dec \o Same as setIntegerBase(10). - \row \o \c hex \o Same as setIntegerBase(16). - \row \o \c showbase \o Same as setNumberFlags(numberFlags() | ShowBase). - \row \o \c forcesign \o Same as setNumberFlags(numberFlags() | ForceSign). - \row \o \c forcepoint \o Same as setNumberFlags(numberFlags() | ForcePoint). - \row \o \c noshowbase \o Same as setNumberFlags(numberFlags() & ~ShowBase). - \row \o \c noforcesign \o Same as setNumberFlags(numberFlags() & ~ForceSign). - \row \o \c noforcepoint \o Same as setNumberFlags(numberFlags() & ~ForcePoint). - \row \o \c uppercasebase \o Same as setNumberFlags(numberFlags() | UppercaseBase). - \row \o \c uppercasedigits \o Same as setNumberFlags(numberFlags() | UppercaseDigits). - \row \o \c lowercasebase \o Same as setNumberFlags(numberFlags() & ~UppercaseBase). - \row \o \c lowercasedigits \o Same as setNumberFlags(numberFlags() & ~UppercaseDigits). - \row \o \c fixed \o Same as setRealNumberNotation(FixedNotation). - \row \o \c scientific \o Same as setRealNumberNotation(ScientificNotation). - \row \o \c left \o Same as setFieldAlignment(AlignLeft). - \row \o \c right \o Same as setFieldAlignment(AlignRight). - \row \o \c center \o Same as setFieldAlignment(AlignCenter). - \row \o \c endl \o Same as operator<<('\n') and flush(). - \row \o \c flush \o Same as flush(). - \row \o \c reset \o Same as reset(). - \row \o \c ws \o Same as skipWhiteSpace(). - \row \o \c bom \o Same as setGenerateByteOrderMark(true). + \header \li Manipulator \li Description + \row \li \c bin \li Same as setIntegerBase(2). + \row \li \c oct \li Same as setIntegerBase(8). + \row \li \c dec \li Same as setIntegerBase(10). + \row \li \c hex \li Same as setIntegerBase(16). + \row \li \c showbase \li Same as setNumberFlags(numberFlags() | ShowBase). + \row \li \c forcesign \li Same as setNumberFlags(numberFlags() | ForceSign). + \row \li \c forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint). + \row \li \c noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase). + \row \li \c noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign). + \row \li \c noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint). + \row \li \c uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase). + \row \li \c uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits). + \row \li \c lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase). + \row \li \c lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits). + \row \li \c fixed \li Same as setRealNumberNotation(FixedNotation). + \row \li \c scientific \li Same as setRealNumberNotation(ScientificNotation). + \row \li \c left \li Same as setFieldAlignment(AlignLeft). + \row \li \c right \li Same as setFieldAlignment(AlignRight). + \row \li \c center \li Same as setFieldAlignment(AlignCenter). + \row \li \c endl \li Same as operator<<('\n') and flush(). + \row \li \c flush \li Same as flush(). + \row \li \c reset \li Same as reset(). + \row \li \c ws \li Same as skipWhiteSpace(). + \row \li \c bom \li Same as setGenerateByteOrderMark(true). \endtable In addition, Qt provides three global manipulators that take a @@ -2065,12 +2065,12 @@ QTextStream &QTextStream::operator>>(char &c) number using the following rules: \table - \header \o Prefix \o Base - \row \o "0b" or "0B" \o 2 (binary) - \row \o "0" followed by "0-7" \o 8 (octal) - \row \o "0" otherwise \o 10 (decimal) - \row \o "0x" or "0X" \o 16 (hexadecimal) - \row \o "1" to "9" \o 10 (decimal) + \header \li Prefix \li Base + \row \li "0b" or "0B" \li 2 (binary) + \row \li "0" followed by "0-7" \li 8 (octal) + \row \li "0" otherwise \li 10 (decimal) + \row \li "0x" or "0X" \li 16 (hexadecimal) + \row \li "1" to "9" \li 10 (decimal) \endtable By calling setIntegerBase(), you can specify the integer base diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index eeeca1bf77..0659053937 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -112,7 +112,7 @@ dealing with URLs and strings: \list - \o When creating an QString to contain a URL from a QByteArray or a + \li When creating an QString to contain a URL from a QByteArray or a char*, always use QString::fromUtf8(). \endlist @@ -135,15 +135,15 @@ \list - \o Spaces and "%20": If an encoded URL contains a space, this will be + \li Spaces and "%20": If an encoded URL contains a space, this will be replaced with "%20". If a decoded URL contains "%20", this will be replaced with a single space before the URL is parsed. - \o Single "%" characters: Any occurrences of a percent character "%" not + \li Single "%" characters: Any occurrences of a percent character "%" not followed by exactly two hexadecimal characters (e.g., "13% coverage.html") will be replaced by "%25". - \o Reserved and unreserved characters: An encoded URL should only + \li Reserved and unreserved characters: An encoded URL should only contain a few characters as literals; all other characters should be percent-encoded. In TolerantMode, these characters will be automatically percent-encoded where they are not allowed: @@ -6335,10 +6335,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \section1 Examples: \list - \o qt.nokia.com becomes http://qt.nokia.com - \o ftp.qt.nokia.com becomes ftp://ftp.qt.nokia.com - \o hostname becomes http://hostname - \o /home/user/test.html becomes file:///home/user/test.html + \li qt.nokia.com becomes http://qt.nokia.com + \li ftp.qt.nokia.com becomes ftp://ftp.qt.nokia.com + \li hostname becomes http://hostname + \li /home/user/test.html becomes file:///home/user/test.html \endlist */ QUrl QUrl::fromUserInput(const QString &userInput) diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index a8c3921f45..7a1357959e 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1161,16 +1161,16 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, \e before and \e after they occur: \list - \o An insertRows() implementation must call beginInsertRows() \e before + \li An insertRows() implementation must call beginInsertRows() \e before inserting new rows into the data structure, and endInsertRows() \e{immediately afterwards}. - \o An insertColumns() implementation must call beginInsertColumns() + \li An insertColumns() implementation must call beginInsertColumns() \e before inserting new columns into the data structure, and endInsertColumns() \e{immediately afterwards}. - \o A removeRows() implementation must call beginRemoveRows() \e before + \li A removeRows() implementation must call beginRemoveRows() \e before the rows are removed from the data structure, and endRemoveRows() \e{immediately afterwards}. - \o A removeColumns() implementation must call beginRemoveColumns() + \li A removeColumns() implementation must call beginRemoveColumns() \e before the columns are removed from the data structure, and endRemoveColumns() \e{immediately afterwards}. \endlist @@ -1179,7 +1179,7 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, the chance to take action before any data becomes unavailable. The encapsulation of the insert and remove operations with these begin and end functions also enables the model to manage \l{QPersistentModelIndex} - {persistent model indexes} correctly. \bold{If you want selections to be + {persistent model indexes} correctly. \b{If you want selections to be handled properly, you must ensure that you call these functions.} If you insert or remove an item with children, you do not need to call these functions for the child items. In other words, the parent item will take @@ -1338,11 +1338,11 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, layoutChanged(). In other words, when the structure changes: \list - \o emit layoutAboutToBeChanged - \o Remember the QModelIndex that will change - \o Update your internal data - \o Call changePersistentIndex() - \o emit layoutChanged + \li emit layoutAboutToBeChanged + \li Remember the QModelIndex that will change + \li Update your internal data + \li Call changePersistentIndex() + \li emit layoutChanged \endlist \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), modelReset(), @@ -1500,7 +1500,7 @@ QAbstractItemModel::~QAbstractItemModel() inclusive, under the given \a sourceParent item have been moved to \a destinationParent starting at the row \a destinationRow. - \bold{Note:} Components connected to this signal use it to adapt to changes + \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel implementation, and cannot be explicitly emitted in subclass code. @@ -1516,7 +1516,7 @@ QAbstractItemModel::~QAbstractItemModel() inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent starting at the row \a destinationRow. - \bold{Note:} Components connected to this signal use it to adapt to changes + \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel implementation, and cannot be explicitly emitted in subclass code. @@ -1532,7 +1532,7 @@ QAbstractItemModel::~QAbstractItemModel() inclusive, under the given \a sourceParent item have been moved to \a destinationParent starting at the column \a destinationColumn. - \bold{Note:} Components connected to this signal use it to adapt to changes + \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel implementation, and cannot be explicitly emitted in subclass code. @@ -1548,7 +1548,7 @@ QAbstractItemModel::~QAbstractItemModel() inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent starting at the column \a destinationColumn. - \bold{Note:} Components connected to this signal use it to adapt to changes + \b{Note:} Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel implementation, and cannot be explicitly emitted in subclass code. @@ -1683,7 +1683,7 @@ bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value Returns the data stored under the given \a role for the item referred to by the \a index. - \note If you do not have a value to return, return an \bold invalid + \note If you do not have a value to return, return an \b invalid QVariant instead of returning 0. \sa Qt::ItemDataRole, setData(), headerData() @@ -2437,8 +2437,8 @@ bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &pare \table 80% \row - \o \inlineimage modelview-begin-insert-rows.png Inserting rows - \o Specify the first and last row numbers for the span of rows you + \li \inlineimage modelview-begin-insert-rows.png Inserting rows + \li Specify the first and last row numbers for the span of rows you want to insert into an item in a model. For example, as shown in the diagram, we insert three rows before @@ -2448,8 +2448,8 @@ bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &pare This inserts the three new rows as rows 2, 3, and 4. \row - \o \inlineimage modelview-begin-append-rows.png Appending rows - \o To append rows, insert them after the last row. + \li \inlineimage modelview-begin-append-rows.png Appending rows + \li To append rows, insert them after the last row. For example, as shown in the diagram, we append two rows to a collection of 4 existing rows (ending in row 3), so \a first is 4 @@ -2503,8 +2503,8 @@ void QAbstractItemModel::endInsertRows() \table 80% \row - \o \inlineimage modelview-begin-remove-rows.png Removing rows - \o Specify the first and last row numbers for the span of rows you + \li \inlineimage modelview-begin-remove-rows.png Removing rows + \li Specify the first and last row numbers for the span of rows you want to remove from an item in a model. For example, as shown in the diagram, we remove the two rows from @@ -2616,8 +2616,8 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star \table 80% \row - \o \inlineimage modelview-move-rows-1.png Moving rows to another parent - \o Specify the first and last row numbers for the span of rows in + \li \inlineimage modelview-move-rows-1.png Moving rows to another parent + \li Specify the first and last row numbers for the span of rows in the source parent you want to move in the model. Also specify the row in the destination parent to move the span to. @@ -2630,8 +2630,8 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star This moves the three rows rows 2, 3, and 4 in the source to become 2, 3 and 4 in the destination. Other affected siblings are displaced accordingly. \row - \o \inlineimage modelview-move-rows-2.png Moving rows to append to another parent - \o To append rows to another parent, move them to after the last row. + \li \inlineimage modelview-move-rows-2.png Moving rows to append to another parent + \li To append rows to another parent, move them to after the last row. For example, as shown in the diagram, we move three rows to a collection of 6 existing rows (ending in row 5), so \a destinationChild is 6: @@ -2640,8 +2640,8 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star This moves the target rows to the end of the target parent as 6, 7 and 8. \row - \o \inlineimage modelview-move-rows-3.png Moving rows in the same parent up - \o To move rows within the same parent, specify the row to move them to. + \li \inlineimage modelview-move-rows-3.png Moving rows in the same parent up + \li To move rows within the same parent, specify the row to move them to. For example, as shown in the diagram, we move one item from row 2 to row 0, so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 0. @@ -2655,8 +2655,8 @@ bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int star it is already) \row - \o \inlineimage modelview-move-rows-4.png Moving rows in the same parent down - \o To move rows within the same parent, specify the row to move them to. + \li \inlineimage modelview-move-rows-4.png Moving rows in the same parent down + \li To move rows within the same parent, specify the row to move them to. For example, as shown in the diagram, we move one item from row 2 to row 4, so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 4. @@ -2737,8 +2737,8 @@ void QAbstractItemModel::endMoveRows() \table 80% \row - \o \inlineimage modelview-begin-insert-columns.png Inserting columns - \o Specify the first and last column numbers for the span of columns + \li \inlineimage modelview-begin-insert-columns.png Inserting columns + \li Specify the first and last column numbers for the span of columns you want to insert into an item in a model. For example, as shown in the diagram, we insert three columns @@ -2748,8 +2748,8 @@ void QAbstractItemModel::endMoveRows() This inserts the three new columns as columns 4, 5, and 6. \row - \o \inlineimage modelview-begin-append-columns.png Appending columns - \o To append columns, insert them after the last column. + \li \inlineimage modelview-begin-append-columns.png Appending columns + \li To append columns, insert them after the last column. For example, as shown in the diagram, we append three columns to a collection of six existing columns (ending in column 5), so @@ -2805,8 +2805,8 @@ void QAbstractItemModel::endInsertColumns() \table 80% \row - \o \inlineimage modelview-begin-remove-columns.png Removing columns - \o Specify the first and last column numbers for the span of columns + \li \inlineimage modelview-begin-remove-columns.png Removing columns + \li Specify the first and last column numbers for the span of columns you want to remove from an item in a model. For example, as shown in the diagram, we remove the three columns @@ -3135,16 +3135,16 @@ QModelIndexList QAbstractItemModel::persistentIndexList() const are aware of any changes: \list - \o An insertRows() implementation must call beginInsertRows() + \li An insertRows() implementation must call beginInsertRows() \e before inserting new rows into the data structure, and it must call endInsertRows() \e{immediately afterwards}. - \o An insertColumns() implementation must call beginInsertColumns() + \li An insertColumns() implementation must call beginInsertColumns() \e before inserting new columns into the data structure, and it must call endInsertColumns() \e{immediately afterwards}. - \o A removeRows() implementation must call beginRemoveRows() + \li A removeRows() implementation must call beginRemoveRows() \e before the rows are removed from the data structure, and it must call endRemoveRows() \e{immediately afterwards}. - \o A removeColumns() implementation must call beginRemoveColumns() + \li A removeColumns() implementation must call beginRemoveColumns() \e before the columns are removed from the data structure, and it must call endRemoveColumns() \e{immediately afterwards}. \endlist @@ -3271,10 +3271,10 @@ bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const functions so that all connected views are aware of any changes: \list - \o An insertRows() implementation must call beginInsertRows() + \li An insertRows() implementation must call beginInsertRows() \e before inserting new rows into the data structure, and it must call endInsertRows() \e{immediately afterwards}. - \o A removeRows() implementation must call beginRemoveRows() + \li A removeRows() implementation must call beginRemoveRows() \e before the rows are removed from the data structure, and it must call endRemoveRows() \e{immediately afterwards}. \endlist diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index b7ef69423f..ae9affb862 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -2531,16 +2531,16 @@ void QSortFilterProxyModel::invalidateFilter() the following QVariant types: \list - \o QVariant::Int - \o QVariant::UInt - \o QVariant::LongLong - \o QVariant::ULongLong - \o QVariant::Double - \o QVariant::Char - \o QVariant::Date - \o QVariant::Time - \o QVariant::DateTime - \o QVariant::String + \li QVariant::Int + \li QVariant::UInt + \li QVariant::LongLong + \li QVariant::ULongLong + \li QVariant::Double + \li QVariant::Char + \li QVariant::Date + \li QVariant::Time + \li QVariant::DateTime + \li QVariant::String \endlist Any other type will be converted to a QString using diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index 0eb1974147..cdf9192b27 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -559,7 +559,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const /*! \typedef QJsonArray::iterator::iterator_category - A synonym for \i {std::random_access_iterator_tag} indicating + A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ @@ -793,7 +793,7 @@ bool QJsonArray::operator!=(const QJsonArray &other) const /*! \typedef QJsonArray::const_iterator::iterator_category - A synonym for \i {std::random_access_iterator_tag} indicating + A synonym for \e {std::random_access_iterator_tag} indicating this iterator is a random access iterator. */ diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index b7af8c22cf..a854f73c7e 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -568,7 +568,7 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const /*! \typedef QJsonObject::iterator::iterator_category - A synonym for \i {std::bidirectional_iterator_tag} indicating + A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ @@ -757,7 +757,7 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const /*! \typedef QJsonObject::const_iterator::iterator_category - A synonym for \i {std::bidirectional_iterator_tag} indicating + A synonym for \e {std::bidirectional_iterator_tag} indicating this iterator is a bidirectional iterator. */ diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index 603cba8897..b4a689da60 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -64,12 +64,12 @@ QT_BEGIN_NAMESPACE JSON is a format to store structured data. It has 6 basic data types: \list - \o bool QJsonValue::Bool - \o double QJsonValue::Double - \o string QJsonValue::String - \o array QJsonValue::Array - \o object QJsonValue::Object - \o null QJsonValue::Null + \li bool QJsonValue::Bool + \li double QJsonValue::Double + \li string QJsonValue::String + \li array QJsonValue::Array + \li object QJsonValue::Object + \li null QJsonValue::Null \endlist A value can represent any of the above data types. In addition, QJsonValue has one special @@ -260,16 +260,16 @@ QJsonValue &QJsonValue::operator =(const QJsonValue &other) The conversion will convert QVariant types as follows: \list - \o QVariant::Bool to Bool - \o QVariant::Int - \o QVariant::Double - \o QVariant::LongLong - \o QVariant::ULongLong - \o QVariant::UInt to Double - \o QVariant::String to String - \o QVariant::StringList - \o QVariant::VariantList to Array - \o QVariant::VariantMap to Object + \li QVariant::Bool to Bool + \li QVariant::Int + \li QVariant::Double + \li QVariant::LongLong + \li QVariant::ULongLong + \li QVariant::UInt to Double + \li QVariant::String to String + \li QVariant::StringList + \li QVariant::VariantList to Array + \li QVariant::VariantMap to Object \endlist For all other QVariant types a conversion to a QString will be attempted. If the returned string diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index 3075eab753..b98f3f4a30 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -167,7 +167,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher() event dispatcher exists for the specified thread, this function returns 0. - \bold{Note:} If Qt is built without thread support, the \a thread + \b{Note:} If Qt is built without thread support, the \a thread argument is ignored. */ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread) @@ -192,10 +192,10 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread) \list - \i If events are available, this function returns after processing + \li If events are available, this function returns after processing them. - \i If no events are available, this function will wait until more + \li If no events are available, this function will wait until more are available and return after processing newly available events. \endlist @@ -204,7 +204,7 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread) and no events are available, this function will return immediately. - \bold{Note:} This function does not process events continuously; it + \b{Note:} This function does not process events continuously; it returns after all available events are processed. \sa hasPendingEvents() @@ -349,17 +349,17 @@ void QAbstractEventDispatcher::closingDown() \table \header - \o Platform - \o type + \li Platform + \li type \row - \o Windows - \o MSG + \li Windows + \li MSG \row - \o X11 - \o XEvent + \li X11 + \li XEvent \row - \o Mac - \o NSEvent + \li Mac + \li NSEvent \endtable diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 2d49b271ce..515732bc68 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -715,13 +715,13 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) reimplementing this virtual function is just one of them. All five approaches are listed below: \list 1 - \i Reimplementing paintEvent(), mousePressEvent() and so + \li Reimplementing paintEvent(), mousePressEvent() and so on. This is the commonest, easiest and least powerful way. - \i Reimplementing this function. This is very powerful, providing + \li Reimplementing this function. This is very powerful, providing complete control; but only one subclass can be active at a time. - \i Installing an event filter on QCoreApplication::instance(). Such + \li Installing an event filter on QCoreApplication::instance(). Such an event filter is able to process all events for all widgets, so it's just as powerful as reimplementing notify(); furthermore, it's possible to have more than one application-global event filter. @@ -730,11 +730,11 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) event filters are only called for objects that live in the main thread. - \i Reimplementing QObject::event() (as QWidget does). If you do + \li Reimplementing QObject::event() (as QWidget does). If you do this you get Tab key presses, and you get to see the events before any widget-specific event filters. - \i Installing an event filter on the object. Such an event filter gets all + \li Installing an event filter on the object. Such an event filter gets all the events, including Tab and Shift+Tab key press events, as long as they do not change the focus widget. \endlist diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index dfdd178c35..58e2c5cd2f 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -222,11 +222,11 @@ int QEventLoop::exec(ProcessEventsFlags flags) operation and want to show its progress without allowing user input, i.e. by using the \l ExcludeUserInputEvents flag. - \bold{Notes:} + \b{Notes:} \list - \o This function does not process events continuously; it + \li This function does not process events continuously; it returns after all available events are processed. - \o Specifying the \l WaitForMoreEvents flag makes no sense + \li Specifying the \l WaitForMoreEvents flag makes no sense and will be ignored. \endlist */ diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index d53ba707f7..f962fb7831 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -86,16 +86,16 @@ QT_BEGIN_NAMESPACE The functions you are most likely to find useful are these: \list - \o className() returns the name of a class. - \o superClass() returns the superclass's meta-object. - \o method() and methodCount() provide information + \li className() returns the name of a class. + \li superClass() returns the superclass's meta-object. + \li method() and methodCount() provide information about a class's meta-methods (signals, slots and other \l{Q_INVOKABLE}{invokable} member functions). - \o enumerator() and enumeratorCount() and provide information about + \li enumerator() and enumeratorCount() and provide information about a class's enumerators. - \o propertyCount() and property() provide information about a + \li propertyCount() and property() provide information about a class's properties. - \o constructor() and constructorCount() provide information + \li constructor() and constructorCount() provide information about a class's meta-constructors. \endlist @@ -1051,18 +1051,18 @@ enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value depending on \a type: \list - \o If \a type is Qt::DirectConnection, the member will be invoked immediately. + \li If \a type is Qt::DirectConnection, the member will be invoked immediately. - \o If \a type is Qt::QueuedConnection, + \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the member is invoked as soon as the application enters the main event loop. - \o If \a type is Qt::BlockingQueuedConnection, the method will be invoked in + \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in the same way as for Qt::QueuedConnection, except that the current thread will block until the event is delivered. Using this connection type to communicate between objects in the same thread will lead to deadlocks. - \o If \a type is Qt::AutoConnection, the member is invoked + \li If \a type is Qt::AutoConnection, the member is invoked synchronously if \a obj lives in the same thread as the caller; otherwise it will invoke the member asynchronously. \endlist @@ -1456,13 +1456,13 @@ QMetaMethod::MethodType QMetaMethod::methodType() const \a connectionType: \list - \o If \a connectionType is Qt::DirectConnection, the member will be invoked immediately. + \li If \a connectionType is Qt::DirectConnection, the member will be invoked immediately. - \o If \a connectionType is Qt::QueuedConnection, + \li If \a connectionType is Qt::QueuedConnection, a QEvent will be posted and the member is invoked as soon as the application enters the main event loop. - \o If \a connectionType is Qt::AutoConnection, the member is invoked + \li If \a connectionType is Qt::AutoConnection, the member is invoked synchronously if \a object lives in the same thread as the caller; otherwise it will invoke the member asynchronously. \endlist diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index cfe985da26..3a3464e43e 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -246,12 +246,12 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty functions to access the data: \table - \header \o Tester \o Getter \o Setter \o MIME Types - \row \o hasText() \o text() \o setText() \o \c text/plain - \row \o hasHtml() \o html() \o setHtml() \o \c text/html - \row \o hasUrls() \o urls() \o setUrls() \o \c text/uri-list - \row \o hasImage() \o imageData() \o setImageData() \o \c image/ * - \row \o hasColor() \o colorData() \o setColorData() \o \c application/x-color + \header \li Tester \li Getter \li Setter \li MIME Types + \row \li hasText() \li text() \li setText() \li \c text/plain + \row \li hasHtml() \li html() \li setHtml() \li \c text/html + \row \li hasUrls() \li urls() \li setUrls() \li \c text/uri-list + \row \li hasImage() \li imageData() \li setImageData() \li \c image/ * + \row \li hasColor() \li colorData() \li setColorData() \li \c application/x-color \endtable For example, if your write a widget that accepts URL drags, you @@ -263,15 +263,15 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty object: \list 1 - \o Custom data can be stored directly in a QMimeData object as a + \li Custom data can be stored directly in a QMimeData object as a QByteArray using setData(). For example: \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1 - \o We can subclass QMimeData and reimplement hasFormat(), + \li We can subclass QMimeData and reimplement hasFormat(), formats(), and retrieveData(). - \o If the drag and drop operation occurs within a single + \li If the drag and drop operation occurs within a single application, we can subclass QMimeData and add extra data in it, and use a qobject_cast() in the receiver's drop event handler. For example: diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 8fa5dcdcff..530ddb3f13 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1805,7 +1805,7 @@ void QObject::removeEventFilter(QObject *obj) deleted, the control must return to the event loop from which deleteLater() was called. - \bold{Note:} It is safe to call this function more than once; when the + \b{Note:} It is safe to call this function more than once; when the first deferred deletion event is delivered, any pending events for the object are removed from the event queue. @@ -2123,9 +2123,9 @@ int QObject::receivers(const char *signal) const member in the specified class. \list - \o If member.mobj is 0 then both signalIndex and methodIndex are set to -1. + \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1. - \o If specified member is not a member of obj instance class (or one of + \li If specified member is not a member of obj instance class (or one of its parent classes) then both signalIndex and methodIndex are set to -1. \endlist @@ -2505,7 +2505,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho disconnect() is typically used in three ways, as the following examples demonstrate. \list 1 - \i Disconnect everything connected to an object's signals: + \li Disconnect everything connected to an object's signals: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26 @@ -2513,7 +2513,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27 - \i Disconnect everything connected to a specific signal: + \li Disconnect everything connected to a specific signal: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28 @@ -2521,7 +2521,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29 - \i Disconnect a specific receiver: + \li Disconnect a specific receiver: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30 @@ -2663,11 +2663,11 @@ bool QObject::disconnect(const QObject *sender, const char *signal, if: \list 1 - \i \a signal is not a member of sender class or one of its parent classes. + \li \a signal is not a member of sender class or one of its parent classes. - \i \a method is not a member of receiver class or one of its parent classes. + \li \a method is not a member of receiver class or one of its parent classes. - \i \a signal instance represents not a signal. + \li \a signal instance represents not a signal. \endlist @@ -3339,7 +3339,7 @@ int QObjectPrivate::signalIndex(const char *signalName) const Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent to be sent to the object. - \bold{Note:} Dynamic properties starting with "_q_" are reserved for internal + \b{Note:} Dynamic properties starting with "_q_" are reserved for internal purposes. \sa property(), metaObject(), dynamicPropertyNames() @@ -4091,19 +4091,19 @@ bool QObject::disconnect(const QMetaObject::Connection &connection) disconnect() is typically used in three ways, as the following examples demonstrate. \list 1 - \i Disconnect everything connected to an object's signals: + \li Disconnect everything connected to an object's signals: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26 - \i Disconnect everything connected to a specific signal: + \li Disconnect everything connected to a specific signal: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 47 - \i Disconnect a specific receiver: + \li Disconnect a specific receiver: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30 - \i Disconnect a connection from one specific signal to a specific slot: + \li Disconnect a connection from one specific signal to a specific slot: \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 48 diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp index 936a933d2d..b983bef5fe 100644 --- a/src/corelib/kernel/qpointer.cpp +++ b/src/corelib/kernel/qpointer.cpp @@ -61,13 +61,13 @@ \list - \i When using QPointer on a QWidget (or a subclass of QWidget), previously + \li When using QPointer on a QWidget (or a subclass of QWidget), previously the QPointer would be cleared by the QWidget destructor. Now, the QPointer is cleared by the QObject destructor (since this is when QWeakPointers are cleared). Any QPointers tracking a widget will \b NOT be cleared before the QWidget destructor destroys the children for the widget being tracked. - \i When constructing a QSharedPointer to take ownership of an object after a + \li When constructing a QSharedPointer to take ownership of an object after a QPointer is already tracking the object. Previously, the shared pointer construction would not be affected by the QPointer, but now that QPointer is implemented using QWeakPoiner, constructing the QSharedPointer will diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 640dfc0f94..d8578a8059 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -100,13 +100,13 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, \list - \o Windows: QSharedMemory does not "own" the shared memory segment. + \li Windows: QSharedMemory does not "own" the shared memory segment. When all threads or processes that have an instance of QSharedMemory attached to a particular shared memory segment have either destroyed their instance of QSharedMemory or exited, the Windows kernel releases the shared memory segment automatically. - \o Unix: QSharedMemory "owns" the shared memory segment. When the + \li Unix: QSharedMemory "owns" the shared memory segment. When the last thread or process that has an instance of QSharedMemory attached to a particular shared memory segment detaches from the segment by destroying its instance of QSharedMemory, the Unix kernel @@ -114,7 +114,7 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash. - \o HP-UX: Only one attach to a shared memory segment is allowed per + \li HP-UX: Only one attach to a shared memory segment is allowed per process. This means that QSharedMemory should not be used across multiple threads in the same process in HP-UX. diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp index d7689bb7b1..0a2a66b6b2 100644 --- a/src/corelib/kernel/qsocketnotifier.cpp +++ b/src/corelib/kernel/qsocketnotifier.cpp @@ -111,9 +111,9 @@ QT_BEGIN_NAMESPACE follow these steps when you receive a notification: \list 1 - \o Disable the notifier. - \o Read data from the socket. - \o Re-enable the notifier if you are interested in more data (such as after + \li Disable the notifier. + \li Read data from the socket. + \li Re-enable the notifier if you are interested in more data (such as after having written a new command to a remote server). \endlist @@ -121,12 +121,12 @@ QT_BEGIN_NAMESPACE follow these steps when you receive a notification: \list 1 - \o Disable the notifier. - \o Write as much data as you can (before \c EWOULDBLOCK is returned). - \o Re-enable notifier if you have more data to write. + \li Disable the notifier. + \li Write as much data as you can (before \c EWOULDBLOCK is returned). + \li Re-enable notifier if you have more data to write. \endlist - \bold{Further information:} + \b{Further information:} On Windows, Qt always disables the notifier after getting a notification, and only re-enables it if more data is expected. For example, if data is read from the socket and it can be used to read more, or if reading or @@ -162,7 +162,7 @@ QT_BEGIN_NAMESPACE It is generally advisable to explicitly enable or disable the socket notifier, especially for write notifiers. - \bold{Note for Windows users:} The socket passed to QSocketNotifier + \b{Note for Windows users:} The socket passed to QSocketNotifier will become non-blocking, even if it was created as a blocking socket. \sa setEnabled(), isEnabled() diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp index d0a67834dd..0558f3cb59 100644 --- a/src/corelib/kernel/qsystemsemaphore.cpp +++ b/src/corelib/kernel/qsystemsemaphore.cpp @@ -90,16 +90,16 @@ QT_BEGIN_NAMESPACE When using this class, be aware of the following platform differences: - \bold{Windows:} QSystemSemaphore does not own its underlying system + \b{Windows:} QSystemSemaphore does not own its underlying system semaphore. Windows owns it. This means that when all instances of QSystemSemaphore for a particular key have been destroyed, either by having their destructors called, or because one or more processes crash, Windows removes the underlying system semaphore. - \bold{Unix:} + \b{Unix:} \list - \o QSystemSemaphore owns the underlying system semaphore + \li QSystemSemaphore owns the underlying system semaphore in Unix systems. This means that the last process having an instance of QSystemSemaphore for a particular key must remove the underlying system semaphore in its destructor. If the last process crashes @@ -117,7 +117,7 @@ QT_BEGIN_NAMESPACE {QSystemSemaphore::} {Create}, which will force Unix to reset the resource count in the underlying system semaphore. - \o When a process using QSystemSemaphore terminates for + \li When a process using QSystemSemaphore terminates for any reason, Unix automatically reverses the effect of all acquire operations that were not released. Thus if the process acquires a resource and then exits without releasing it, Unix will release that diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index a11bcb26c9..dad3318870 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -279,9 +279,9 @@ public: up to three parameters: \list - \o The \e context - usually the class name for the tr() caller. - \o The \e {source text} - usually the argument to tr(). - \o The \e disambiguation - an optional string that helps disambiguate + \li The \e context - usually the class name for the tr() caller. + \li The \e {source text} - usually the argument to tr(). + \li The \e disambiguation - an optional string that helps disambiguate different uses of the same text in the same context. \endlist @@ -361,12 +361,12 @@ QTranslator::~QTranslator() in the following order: \list 1 - \o File name without \a suffix appended. - \o File name with text after a character in \a search_delimiters + \li File name without \a suffix appended. + \li File name with text after a character in \a search_delimiters stripped ("_." is the default for \a search_delimiters if it is an empty string) and \a suffix. - \o File name stripped without \a suffix appended. - \o File name stripped further, etc. + \li File name stripped without \a suffix appended. + \li File name stripped further, etc. \endlist For example, an application running in the fr_CA locale @@ -375,12 +375,12 @@ QTranslator::~QTranslator() readable file from this list: \list 1 - \o \c /opt/foolib/foo.fr_ca.qm - \o \c /opt/foolib/foo.fr_ca - \o \c /opt/foolib/foo.fr.qm - \o \c /opt/foolib/foo.fr - \o \c /opt/foolib/foo.qm - \o \c /opt/foolib/foo + \li \c /opt/foolib/foo.fr_ca.qm + \li \c /opt/foolib/foo.fr_ca + \li \c /opt/foolib/foo.fr.qm + \li \c /opt/foolib/foo.fr + \li \c /opt/foolib/foo.qm + \li \c /opt/foolib/foo \endlist */ @@ -599,10 +599,10 @@ static QString find_translation(const QLocale & locale, in the following order: \list 1 - \o File name without \a suffix appended. - \o File name with ui language part after a "_" character stripped and \a suffix. - \o File name with ui language part stripped without \a suffix appended. - \o File name with ui language part stripped further, etc. + \li File name without \a suffix appended. + \li File name with ui language part after a "_" character stripped and \a suffix. + \li File name with ui language part stripped without \a suffix appended. + \li File name with ui language part stripped further, etc. \endlist For example, an application running in the locale with the following @@ -612,17 +612,17 @@ static QString find_translation(const QLocale & locale, open the first existing readable file from this list: \list 1 - \o \c /opt/foolib/foo.es.qm - \o \c /opt/foolib/foo.es - \o \c /opt/foolib/foo.fr_CA.qm - \o \c /opt/foolib/foo.fr_CA - \o \c /opt/foolib/foo.de.qm - \o \c /opt/foolib/foo.de - \o \c /opt/foolib/foo.fr.qm - \o \c /opt/foolib/foo.fr - \o \c /opt/foolib/foo.qm - \o \c /opt/foolib/foo. - \o \c /opt/foolib/foo + \li \c /opt/foolib/foo.es.qm + \li \c /opt/foolib/foo.es + \li \c /opt/foolib/foo.fr_CA.qm + \li \c /opt/foolib/foo.fr_CA + \li \c /opt/foolib/foo.de.qm + \li \c /opt/foolib/foo.de + \li \c /opt/foolib/foo.fr.qm + \li \c /opt/foolib/foo.fr + \li \c /opt/foolib/foo.qm + \li \c /opt/foolib/foo. + \li \c /opt/foolib/foo \endlist On operating systems where file system is case sensitive, QTranslator also diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 1c18883fde..4f3e4f8b4e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2174,7 +2174,7 @@ inline T qNumVariantToHelper(const QVariant::Private &d, If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be converted to an int; otherwise \c{*}\a{ok} is set to false. - \bold{Warning:} If the value is convertible to a \l LongLong but is too + \b{Warning:} If the value is convertible to a \l LongLong but is too large to be represented in an int, the resulting arithmetic overflow will not be reflected in \a ok. A simple workaround is to use QString::toInt(). Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code. @@ -2194,7 +2194,7 @@ int QVariant::toInt(bool *ok) const If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be converted to an unsigned int; otherwise \c{*}\a{ok} is set to false. - \bold{Warning:} If the value is convertible to a \l ULongLong but is too + \b{Warning:} If the value is convertible to a \l ULongLong but is too large to be represented in an unsigned int, the resulting arithmetic overflow will not be reflected in \a ok. A simple workaround is to use QString::toUInt(). Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code. @@ -2411,28 +2411,28 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = The following casts are done automatically: \table - \header \o Type \o Automatically Cast To - \row \o \l Bool \o \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong - \row \o \l ByteArray \o \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong - \row \o \l Char \o \l Bool, \l Int, \l UInt, \l LongLong, \l ULongLong - \row \o \l Color \o \l String - \row \o \l Date \o \l DateTime, \l String - \row \o \l DateTime \o \l Date, \l String, \l Time - \row \o \l Double \o \l Bool, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong - \row \o \l Font \o \l String - \row \o \l Int \o \l Bool, \l Char, \l Double, \l LongLong, \l String, \l UInt, \l ULongLong - \row \o \l KeySequence \o \l Int, \l String - \row \o \l List \o \l StringList (if the list's items can be converted to strings) - \row \o \l LongLong \o \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l String, \l UInt, \l ULongLong - \row \o \l Point \o PointF - \row \o \l Rect \o RectF - \row \o \l String \o \l Bool, \l ByteArray, \l Char, \l Color, \l Date, \l DateTime, \l Double, + \header \li Type \li Automatically Cast To + \row \li \l Bool \li \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong + \row \li \l ByteArray \li \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong + \row \li \l Char \li \l Bool, \l Int, \l UInt, \l LongLong, \l ULongLong + \row \li \l Color \li \l String + \row \li \l Date \li \l DateTime, \l String + \row \li \l DateTime \li \l Date, \l String, \l Time + \row \li \l Double \li \l Bool, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong + \row \li \l Font \li \l String + \row \li \l Int \li \l Bool, \l Char, \l Double, \l LongLong, \l String, \l UInt, \l ULongLong + \row \li \l KeySequence \li \l Int, \l String + \row \li \l List \li \l StringList (if the list's items can be converted to strings) + \row \li \l LongLong \li \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l String, \l UInt, \l ULongLong + \row \li \l Point \li PointF + \row \li \l Rect \li RectF + \row \li \l String \li \l Bool, \l ByteArray, \l Char, \l Color, \l Date, \l DateTime, \l Double, \l Font, \l Int, \l KeySequence, \l LongLong, \l StringList, \l Time, \l UInt, \l ULongLong - \row \o \l StringList \o \l List, \l String (if the list contains exactly one item) - \row \o \l Time \o \l String - \row \o \l UInt \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l ULongLong - \row \o \l ULongLong \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt + \row \li \l StringList \li \l List, \l String (if the list contains exactly one item) + \row \li \l Time \li \l String + \row \li \l UInt \li \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l ULongLong + \row \li \l ULongLong \li \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt \endtable \sa convert() diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 11a2dc83f5..58ca046d9d 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE Finally, you can use the setHandle() function to register a new event object, and the handle() function to retrieve the event handle. - \bold{Further information:} + \b{Further information:} Although the class is called QWinEventNotifier, it can be used for certain other objects which are so-called synchronization objects, such as Processes, Threads, Waitable timers. @@ -140,7 +140,7 @@ QWinEventNotifier::~QWinEventNotifier() Register the HANDLE \a hEvent. The old HANDLE will be automatically unregistered. - \bold Note: The notifier will be disabled as a side effect and needs + \b Note: The notifier will be disabled as a side effect and needs to be re-enabled. \sa handle(), setEnabled() diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index b171577184..216e6e1e7c 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -596,12 +596,12 @@ bool QLibraryPrivate::loadPlugin() library; otherwise returns false. \table - \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll, \c .DLL - \row \i Unix/Linux \i \c .so - \row \i AIX \i \c .a - \row \i HP-UX \i \c .sl, \c .so (HP-UXi) - \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so + \header \li Platform \li Valid suffixes + \row \li Windows \li \c .dll, \c .DLL + \row \li Unix/Linux \li \c .so + \row \li AIX \li \c .a + \row \li HP-UX \li \c .sl, \c .so (HP-UXi) + \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so \endtable Trailing versioning numbers on Unix are ignored. diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index d652b251f1..f198f108da 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -66,9 +66,9 @@ QT_BEGIN_NAMESPACE using QLibrary: \list - \o QPluginLoader checks that a plugin is linked against the same + \li QPluginLoader checks that a plugin is linked against the same version of Qt as the application. - \o QPluginLoader provides direct access to a root component object + \li QPluginLoader provides direct access to a root component object (instance()), instead of forcing you to resolve a C function manually. \endlist diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 3d7988a8fc..26032323e0 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -190,34 +190,34 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto \table \header - \o msb0 - \o msb1 - \o msb2 - \o Variant + \li msb0 + \li msb1 + \li msb2 + \li Variant \row - \o 0 - \o x - \o x - \o NCS (Network Computing System) + \li 0 + \li x + \li x + \li NCS (Network Computing System) \row - \o 1 - \o 0 - \o x - \o DCE (Distributed Computing Environment) + \li 1 + \li 0 + \li x + \li DCE (Distributed Computing Environment) \row - \o 1 - \o 1 - \o 0 - \o Microsoft (GUID) + \li 1 + \li 1 + \li 0 + \li Microsoft (GUID) \row - \o 1 - \o 1 - \o 1 - \o Reserved for future expansion + \li 1 + \li 1 + \li 1 + \li Reserved for future expansion \endtable @@ -234,46 +234,46 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto \table \header - \o msb0 - \o msb1 - \o msb2 - \o msb3 - \o Version + \li msb0 + \li msb1 + \li msb2 + \li msb3 + \li Version \row - \o 0 - \o 0 - \o 0 - \o 1 - \o Time + \li 0 + \li 0 + \li 0 + \li 1 + \li Time \row - \o 0 - \o 0 - \o 1 - \o 0 - \o Embedded POSIX + \li 0 + \li 0 + \li 1 + \li 0 + \li Embedded POSIX \row - \o 0 - \o 0 - \o 1 - \o 1 - \o Md5(Name) + \li 0 + \li 0 + \li 1 + \li 1 + \li Md5(Name) \row - \o 0 - \o 1 - \o 0 - \o 0 - \o Random + \li 0 + \li 1 + \li 0 + \li 0 + \li Random \row - \o 0 - \o 1 - \o 0 - \o 1 - \o Sha1 + \li 0 + \li 1 + \li 0 + \li 1 + \li Sha1 \endtable @@ -516,28 +516,28 @@ QUuid QUuid::fromRfc4122(const QByteArray &bytes) \table \header - \o Field # - \o Source + \li Field # + \li Source \row - \o 1 - \o data1 + \li 1 + \li data1 \row - \o 2 - \o data2 + \li 2 + \li data2 \row - \o 3 - \o data3 + \li 3 + \li data3 \row - \o 4 - \o data4[0] .. data4[1] + \li 4 + \li data4[0] .. data4[1] \row - \o 5 - \o data4[2] .. data4[7] + \li 5 + \li data4[2] .. data4[7] \endtable */ @@ -560,28 +560,28 @@ QString QUuid::toString() const \table \header - \o Field # - \o Source + \li Field # + \li Source \row - \o 1 - \o data1 + \li 1 + \li data1 \row - \o 2 - \o data2 + \li 2 + \li data2 \row - \o 3 - \o data3 + \li 3 + \li data3 \row - \o 4 - \o data4[0] .. data4[1] + \li 4 + \li data4[0] .. data4[1] \row - \o 5 - \o data4[2] .. data4[7] + \li 5 + \li data4[2] .. data4[7] \endtable @@ -607,24 +607,24 @@ QByteArray QUuid::toByteArray() const \table \header - \o Field # - \o Source + \li Field # + \li Source \row - \o 1 - \o data1 + \li 1 + \li data1 \row - \o 2 - \o data2 + \li 2 + \li data2 \row - \o 3 - \o data3 + \li 3 + \li data3 \row - \o 4 - \o data4[0] .. data4[7] + \li 4 + \li data4[0] .. data4[7] \endtable diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index 5443d6e1b6..2e3029f3fa 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -83,16 +83,16 @@ \list - \o Relaxed - memory ordering is unspecified, leaving the compiler + \li Relaxed - memory ordering is unspecified, leaving the compiler and processor to freely reorder memory accesses. - \o Acquire - memory access following the atomic operation (in + \li Acquire - memory access following the atomic operation (in program order) may not be re-ordered before the atomic operation. - \o Release - memory access before the atomic operation (in program + \li Release - memory access before the atomic operation (in program order) may not be re-ordered after the atomic operation. - \o Ordered - the same Acquire and Release semantics combined. + \li Ordered - the same Acquire and Release semantics combined. \endlist @@ -180,25 +180,25 @@ \list - \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE - \o Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE + \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + \li Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE - \o Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE - \o Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE - \o Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + \li Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + \li Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + \li Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE - \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE - \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE - \o Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE + \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + \li Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE \endlist @@ -658,16 +658,16 @@ \list - \o Relaxed - memory ordering is unspecified, leaving the compiler + \li Relaxed - memory ordering is unspecified, leaving the compiler and processor to freely reorder memory accesses. - \o Acquire - memory access following the atomic operation (in + \li Acquire - memory access following the atomic operation (in program order) may not be re-ordered before the atomic operation. - \o Release - memory access before the atomic operation (in program + \li Release - memory access before the atomic operation (in program order) may not be re-ordered after the atomic operation. - \o Ordered - the same Acquire and Release semantics combined. + \li Ordered - the same Acquire and Release semantics combined. \endlist @@ -753,20 +753,20 @@ \list - \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE - \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE - \o Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + \li Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + \li Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + \li Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE - \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + \li Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE - \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE - \o Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE + \li Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + \li Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE \endlist diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 52f5a1d699..08952eeaa3 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -66,10 +66,10 @@ QT_BEGIN_NAMESPACE release(): \list - \o acquire(\e{n}) tries to acquire \e n resources. If there aren't + \li acquire(\e{n}) tries to acquire \e n resources. If there aren't that many resources available, the call will block until this is the case. - \o release(\e{n}) releases \e n resources. + \li release(\e{n}) releases \e n resources. \endlist There's also a tryAcquire() function that returns immediately if diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a071463178..64fd8776ce 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -658,11 +658,11 @@ QThread::Priority QThread::priority() const Blocks the thread until either of these conditions is met: \list - \o The thread associated with this QThread object has finished + \li The thread associated with this QThread object has finished execution (i.e. when it returns from \l{run()}). This function will return true if the thread has finished. It also returns true if the thread has not been started yet. - \o \a time milliseconds has elapsed. If \a time is ULONG_MAX (the + \li \a time milliseconds has elapsed. If \a time is ULONG_MAX (the default), then the wait will never timeout (the thread must return from \l{run()}). This function will return false if the wait timed out. diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 1dfa3305bc..68db8fe261 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -246,11 +246,11 @@ void QThreadStorageData::finish(void **p) \list - \o The QThreadStorage destructor does not delete per-thread data. + \li The QThreadStorage destructor does not delete per-thread data. QThreadStorage only deletes per-thread data when the thread exits or when setLocalData() is called multiple times. - \o QThreadStorage can be used to store data for the \c main() + \li QThreadStorage can be used to store data for the \c main() thread. QThreadStorage deletes all data set for the \c main() thread when QApplication is destroyed, regardless of whether or not the \c main() thread has actually finished. diff --git a/src/corelib/thread/qwaitcondition.qdoc b/src/corelib/thread/qwaitcondition.qdoc index 7b861f8f7a..8c93bd167d 100644 --- a/src/corelib/thread/qwaitcondition.qdoc +++ b/src/corelib/thread/qwaitcondition.qdoc @@ -129,9 +129,9 @@ calling thread will block until either of these conditions is met: \list - \o Another thread signals it using wakeOne() or wakeAll(). This + \li Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case. - \o \a time milliseconds has elapsed. If \a time is \c ULONG_MAX + \li \a time milliseconds has elapsed. If \a time is \c ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out. @@ -157,9 +157,9 @@ calling thread will block until either of these conditions is met: \list - \o Another thread signals it using wakeOne() or wakeAll(). This + \li Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case. - \o \a time milliseconds has elapsed. If \a time is \c ULONG_MAX + \li \a time milliseconds has elapsed. If \a time is \c ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out. diff --git a/src/corelib/tools/qalgorithms.qdoc b/src/corelib/tools/qalgorithms.qdoc index a16ed8b3dc..5a4a278ad0 100644 --- a/src/corelib/tools/qalgorithms.qdoc +++ b/src/corelib/tools/qalgorithms.qdoc @@ -159,14 +159,14 @@ bidirectional iterator, and supports the following operations: \table - \row \i \c{i += n} \i advances iterator \c i by \c n positions - \row \i \c{i -= n} \i moves iterator \c i back by \c n positions - \row \i \c{i + n} or \c{n + i} \i returns the iterator for the item \c + \row \li \c{i += n} \li advances iterator \c i by \c n positions + \row \li \c{i -= n} \li moves iterator \c i back by \c n positions + \row \li \c{i + n} or \c{n + i} \li returns the iterator for the item \c n positions ahead of iterator \c i - \row \i \c{i - n} \i returns the iterator for the item \c n positions behind of iterator \c i - \row \i \c{i - j} \i returns the number of items between iterators \c i and \c j - \row \i \c{i[n]} \i same as \c{*(i + n)} - \row \i \c{i < j} \i returns true if iterator \c j comes after iterator \c i + \row \li \c{i - n} \li returns the iterator for the item \c n positions behind of iterator \c i + \row \li \c{i - j} \li returns the number of items between iterators \c i and \c j + \row \li \c{i[n]} \li same as \c{*(i + n)} + \row \li \c{i < j} \li returns true if iterator \c j comes after iterator \c i \endtable QList and QVector's non-const iterator types are random access iterators. diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index c74c61999d..445fe5cd81 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -505,7 +505,7 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) from this and any earlier Qt version, back to Qt 3.1 when this feature was added. - \bold{Note:} If you want to use this function to uncompress external + \b{Note:} If you want to use this function to uncompress external data that was compressed using zlib, you first need to prepend a four byte header to the byte array containing the data. The header must contain the expected length (in bytes) of the uncompressed data, @@ -3687,12 +3687,12 @@ QByteArray &QByteArray::setNum(qulonglong n, int base) The format \a f can be any of the following: \table - \header \i Format \i Meaning - \row \i \c e \i format as [-]9.9e[+|-]999 - \row \i \c E \i format as [-]9.9E[+|-]999 - \row \i \c f \i format as [-]9.9 - \row \i \c g \i use \c e or \c f format, whichever is the most concise - \row \i \c G \i use \c E or \c f format, whichever is the most concise + \header \li Format \li Meaning + \row \li \c e \li format as [-]9.9e[+|-]999 + \row \li \c E \li format as [-]9.9E[+|-]999 + \row \li \c f \li format as [-]9.9 + \row \li \c g \li use \c e or \c f format, whichever is the most concise + \row \li \c G \li use \c E or \c f format, whichever is the most concise \endtable With 'e', 'E', and 'f', \a prec is the number of digits after the @@ -3816,12 +3816,12 @@ QByteArray QByteArray::number(qulonglong n, int base) which is \c g by default, and can be any of the following: \table - \header \i Format \i Meaning - \row \i \c e \i format as [-]9.9e[+|-]999 - \row \i \c E \i format as [-]9.9E[+|-]999 - \row \i \c f \i format as [-]9.9 - \row \i \c g \i use \c e or \c f format, whichever is the most concise - \row \i \c G \i use \c E or \c f format, whichever is the most concise + \header \li Format \li Meaning + \row \li \c e \li format as [-]9.9e[+|-]999 + \row \li \c E \li format as [-]9.9E[+|-]999 + \row \li \c f \li format as [-]9.9 + \row \li \c g \li use \c e or \c f format, whichever is the most concise + \row \li \c G \li use \c E or \c f format, whichever is the most concise \endtable With 'e', 'E', and 'f', \a prec is the number of digits after the diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 70efb5db22..64ad3121d0 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -306,18 +306,18 @@ int QDate::year() const the following convention: \list - \i 1 = "January" - \i 2 = "February" - \i 3 = "March" - \i 4 = "April" - \i 5 = "May" - \i 6 = "June" - \i 7 = "July" - \i 8 = "August" - \i 9 = "September" - \i 10 = "October" - \i 11 = "November" - \i 12 = "December" + \li 1 = "January" + \li 2 = "February" + \li 3 = "March" + \li 4 = "April" + \li 5 = "May" + \li 6 = "June" + \li 7 = "July" + \li 8 = "August" + \li 9 = "September" + \li 10 = "October" + \li 11 = "November" + \li 12 = "December" \endlist Returns 0 if the date is invalid. @@ -521,18 +521,18 @@ int QDate::weekNumber(int *yearNumber) const The months are enumerated using the following convention: \list - \i 1 = "Jan" - \i 2 = "Feb" - \i 3 = "Mar" - \i 4 = "Apr" - \i 5 = "May" - \i 6 = "Jun" - \i 7 = "Jul" - \i 8 = "Aug" - \i 9 = "Sep" - \i 10 = "Oct" - \i 11 = "Nov" - \i 12 = "Dec" + \li 1 = "Jan" + \li 2 = "Feb" + \li 3 = "Mar" + \li 4 = "Apr" + \li 5 = "May" + \li 6 = "Jun" + \li 7 = "Jul" + \li 8 = "Aug" + \li 9 = "Sep" + \li 10 = "Oct" + \li 11 = "Nov" + \li 12 = "Dec" \endlist The month names will be localized according to the system's locale @@ -568,18 +568,18 @@ QString QDate::shortMonthName(int month, QDate::MonthNameType type) The months are enumerated using the following convention: \list - \i 1 = "January" - \i 2 = "February" - \i 3 = "March" - \i 4 = "April" - \i 5 = "May" - \i 6 = "June" - \i 7 = "July" - \i 8 = "August" - \i 9 = "September" - \i 10 = "October" - \i 11 = "November" - \i 12 = "December" + \li 1 = "January" + \li 2 = "February" + \li 3 = "March" + \li 4 = "April" + \li 5 = "May" + \li 6 = "June" + \li 7 = "July" + \li 8 = "August" + \li 9 = "September" + \li 10 = "October" + \li 11 = "November" + \li 12 = "December" \endlist The month names will be localized according to the system's locale @@ -615,13 +615,13 @@ QString QDate::longMonthName(int month, MonthNameType type) The days are enumerated using the following convention: \list - \i 1 = "Mon" - \i 2 = "Tue" - \i 3 = "Wed" - \i 4 = "Thu" - \i 5 = "Fri" - \i 6 = "Sat" - \i 7 = "Sun" + \li 1 = "Mon" + \li 2 = "Tue" + \li 3 = "Wed" + \li 4 = "Thu" + \li 5 = "Fri" + \li 6 = "Sat" + \li 7 = "Sun" \endlist The day names will be localized according to the system's locale @@ -657,13 +657,13 @@ QString QDate::shortDayName(int weekday, MonthNameType type) The days are enumerated using the following convention: \list - \i 1 = "Monday" - \i 2 = "Tuesday" - \i 3 = "Wednesday" - \i 4 = "Thursday" - \i 5 = "Friday" - \i 6 = "Saturday" - \i 7 = "Sunday" + \li 1 = "Monday" + \li 2 = "Tuesday" + \li 3 = "Wednesday" + \li 4 = "Thursday" + \li 5 = "Friday" + \li 6 = "Saturday" + \li 7 = "Sunday" \endlist The day names will be localized according to the system's locale @@ -781,25 +781,25 @@ QString QDate::toString(Qt::DateFormat f) const These expressions may be used: \table - \header \i Expression \i Output - \row \i d \i the day as number without a leading zero (1 to 31) - \row \i dd \i the day as number with a leading zero (01 to 31) - \row \i ddd - \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \header \li Expression \li Output + \row \li d \li the day as number without a leading zero (1 to 31) + \row \li dd \li the day as number with a leading zero (01 to 31) + \row \li ddd + \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). - \row \i dddd - \i the long localized day name (e.g. 'Monday' to 'Sunday'). + \row \li dddd + \li the long localized day name (e.g. 'Monday' to 'Sunday'). Uses QDate::longDayName(). - \row \i M \i the month as number without a leading zero (1 to 12) - \row \i MM \i the month as number with a leading zero (01 to 12) - \row \i MMM - \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li M \li the month as number without a leading zero (1 to 12) + \row \li MM \li the month as number with a leading zero (01 to 12) + \row \li MMM + \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). - \row \i MMMM - \i the long localized month name (e.g. 'January' to 'December'). + \row \li MMMM + \li the long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). - \row \i yy \i the year as two digit number (00 to 99) - \row \i yyyy \i the year as four digit number. If the year is negative, + \row \li yy \li the year as two digit number (00 to 99) + \row \li yyyy \li the year as four digit number. If the year is negative, a minus sign is prepended in addition. \endtable @@ -812,10 +812,10 @@ QString QDate::toString(Qt::DateFormat f) const 1969): \table - \header \o Format \o Result - \row \o dd.MM.yyyy \o 20.07.1969 - \row \o ddd MMMM d yy \o Sun July 20 69 - \row \o 'The day is' dddd \o The day is Sunday + \header \li Format \li Result + \row \li dd.MM.yyyy \li 20.07.1969 + \row \li ddd MMMM d yy \li Sun July 20 69 + \row \li 'The day is' dddd \li The day is Sunday \endtable If the datetime is invalid, an empty string will be returned. @@ -1191,25 +1191,25 @@ QDate QDate::fromString(const QString& s, Qt::DateFormat f) These expressions may be used for the format: \table - \header \i Expression \i Output - \row \i d \i The day as a number without a leading zero (1 to 31) - \row \i dd \i The day as a number with a leading zero (01 to 31) - \row \i ddd - \i The abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \header \li Expression \li Output + \row \li d \li The day as a number without a leading zero (1 to 31) + \row \li dd \li The day as a number with a leading zero (01 to 31) + \row \li ddd + \li The abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). - \row \i dddd - \i The long localized day name (e.g. 'Monday' to 'Sunday'). + \row \li dddd + \li The long localized day name (e.g. 'Monday' to 'Sunday'). Uses QDate::longDayName(). - \row \i M \i The month as a number without a leading zero (1 to 12) - \row \i MM \i The month as a number with a leading zero (01 to 12) - \row \i MMM - \i The abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li M \li The month as a number without a leading zero (1 to 12) + \row \li MM \li The month as a number with a leading zero (01 to 12) + \row \li MMM + \li The abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). - \row \i MMMM - \i The long localized month name (e.g. 'January' to 'December'). + \row \li MMMM + \li The long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). - \row \i yy \i The year as two digit number (00 to 99) - \row \i yyyy \i The year as four digit number. If the year is negative, + \row \li yy \li The year as two digit number (00 to 99) + \row \li yyyy \li The year as four digit number. If the year is negative, a minus sign is prepended in addition. \endtable @@ -1233,10 +1233,10 @@ QDate QDate::fromString(const QString& s, Qt::DateFormat f) defaults are used: \table - \header \i Field \i Default value - \row \i Year \i 1900 - \row \i Month \i 1 - \row \i Day \i 1 + \header \li Field \li Default value + \row \li Year \li 1900 + \row \li Month \li 1 + \row \li Day \li 1 \endtable The following examples demonstrate the default values: @@ -1543,26 +1543,26 @@ QString QTime::toString(Qt::DateFormat format) const These expressions may be used: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i H - \i the hour without a leading zero (0 to 23, even with AM/PM display) - \row \i HH - \i the hour with a leading zero (00 to 23, even with AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP or A - \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". - \row \i ap or a - \i use am/pm display. \e ap will be replaced by either "am" or "pm". - \row \i t \i the timezone (for example "CEST") + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li H + \li the hour without a leading zero (0 to 23, even with AM/PM display) + \row \li HH + \li the hour with a leading zero (00 to 23, even with AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP or A + \li use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \li ap or a + \li use am/pm display. \e ap will be replaced by either "am" or "pm". + \row \li t \li the timezone (for example "CEST") \endtable All other input characters will be ignored. Any sequence of characters that @@ -1573,10 +1573,10 @@ QString QTime::toString(Qt::DateFormat format) const Example format strings (assuming that the QTime is 14:13:09.042) \table - \header \i Format \i Result - \row \i hh:mm:ss.zzz \i 14:13:09.042 - \row \i h:m:s ap \i 2:13:9 pm - \row \i H:m:s a \i 14:13:9 pm + \header \li Format \li Result + \row \li hh:mm:ss.zzz \li 14:13:09.042 + \row \li h:m:s ap \li 2:13:9 pm + \row \li H:m:s a \li 14:13:9 pm \endtable If the datetime is invalid, an empty string will be returned. @@ -1824,21 +1824,21 @@ QTime QTime::fromString(const QString& s, Qt::DateFormat f) These expressions may be used for the format: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP - \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". - \row \i ap - \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP + \li interpret as an AM/PM time. \e AP must be either "AM" or "PM". + \row \li ap + \li Interpret as an AM/PM time. \e ap must be either "am" or "pm". \endtable All other input characters will be treated as text. Any sequence @@ -2515,45 +2515,45 @@ QString QDateTime::toString(Qt::DateFormat f) const These expressions may be used for the date: \table - \header \i Expression \i Output - \row \i d \i the day as number without a leading zero (1 to 31) - \row \i dd \i the day as number with a leading zero (01 to 31) - \row \i ddd - \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \header \li Expression \li Output + \row \li d \li the day as number without a leading zero (1 to 31) + \row \li dd \li the day as number with a leading zero (01 to 31) + \row \li ddd + \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). - \row \i dddd - \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). + \row \li dddd + \li the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). Uses QDate::longDayName(). - \row \i M \i the month as number without a leading zero (1-12) - \row \i MM \i the month as number with a leading zero (01-12) - \row \i MMM - \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li M \li the month as number without a leading zero (1-12) + \row \li MM \li the month as number with a leading zero (01-12) + \row \li MMM + \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). - \row \i MMMM - \i the long localized month name (e.g. 'January' to 'December'). + \row \li MMMM + \li the long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). - \row \i yy \i the year as two digit number (00-99) - \row \i yyyy \i the year as four digit number + \row \li yy \li the year as two digit number (00-99) + \row \li yyyy \li the year as four digit number \endtable These expressions may be used for the time: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP - \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". - \row \i ap - \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP + \li use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \li ap + \li use am/pm display. \e ap will be replaced by either "am" or "pm". \endtable All other input characters will be ignored. Any sequence of characters that @@ -2565,11 +2565,11 @@ QString QDateTime::toString(Qt::DateFormat f) const 14:13:09): \table - \header \i Format \i Result - \row \i dd.MM.yyyy \i 21.05.2001 - \row \i ddd MMMM d yy \i Tue May 21 01 - \row \i hh:mm:ss.zzz \i 14:13:09.042 - \row \i h:m:s ap \i 2:13:9 pm + \header \li Format \li Result + \row \li dd.MM.yyyy \li 21.05.2001 + \row \li ddd MMMM d yy \li Tue May 21 01 + \row \li hh:mm:ss.zzz \li 14:13:09.042 + \row \li h:m:s ap \li 2:13:9 pm \endtable If the datetime is invalid, an empty string will be returned. @@ -3367,25 +3367,25 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) These expressions may be used for the date part of the format string: \table - \header \i Expression \i Output - \row \i d \i the day as number without a leading zero (1 to 31) - \row \i dd \i the day as number with a leading zero (01 to 31) - \row \i ddd - \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + \header \li Expression \li Output + \row \li d \li the day as number without a leading zero (1 to 31) + \row \li dd \li the day as number with a leading zero (01 to 31) + \row \li ddd + \li the abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses QDate::shortDayName(). - \row \i dddd - \i the long localized day name (e.g. 'Monday' to 'Sunday'). + \row \li dddd + \li the long localized day name (e.g. 'Monday' to 'Sunday'). Uses QDate::longDayName(). - \row \i M \i the month as number without a leading zero (1-12) - \row \i MM \i the month as number with a leading zero (01-12) - \row \i MMM - \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + \row \li M \li the month as number without a leading zero (1-12) + \row \li MM \li the month as number with a leading zero (01-12) + \row \li MMM + \li the abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses QDate::shortMonthName(). - \row \i MMMM - \i the long localized month name (e.g. 'January' to 'December'). + \row \li MMMM + \li the long localized month name (e.g. 'January' to 'December'). Uses QDate::longMonthName(). - \row \i yy \i the year as two digit number (00-99) - \row \i yyyy \i the year as four digit number + \row \li yy \li the year as two digit number (00-99) + \row \li yyyy \li the year as four digit number \endtable \note Unlike the other version of this function, day and month names must @@ -3395,25 +3395,25 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) These expressions may be used for the time part of the format string: \table - \header \i Expression \i Output - \row \i h - \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) - \row \i hh - \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) - \row \i H - \i the hour without a leading zero (0 to 23, even with AM/PM display) - \row \i HH - \i the hour with a leading zero (00 to 23, even with AM/PM display) - \row \i m \i the minute without a leading zero (0 to 59) - \row \i mm \i the minute with a leading zero (00 to 59) - \row \i s \i the second without a leading zero (0 to 59) - \row \i ss \i the second with a leading zero (00 to 59) - \row \i z \i the milliseconds without leading zeroes (0 to 999) - \row \i zzz \i the milliseconds with leading zeroes (000 to 999) - \row \i AP or A - \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". - \row \i ap or a - \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". + \header \li Expression \li Output + \row \li h + \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \li hh + \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \li H + \li the hour without a leading zero (0 to 23, even with AM/PM display) + \row \li HH + \li the hour with a leading zero (00 to 23, even with AM/PM display) + \row \li m \li the minute without a leading zero (0 to 59) + \row \li mm \li the minute with a leading zero (00 to 59) + \row \li s \li the second without a leading zero (0 to 59) + \row \li ss \li the second with a leading zero (00 to 59) + \row \li z \li the milliseconds without leading zeroes (0 to 999) + \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li AP or A + \li interpret as an AM/PM time. \e AP must be either "AM" or "PM". + \row \li ap or a + \li Interpret as an AM/PM time. \e ap must be either "am" or "pm". \endtable All other input characters will be treated as text. Any sequence @@ -3437,13 +3437,13 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) defaults are used: \table - \header \i Field \i Default value - \row \i Year \i 1900 - \row \i Month \i 1 (January) - \row \i Day \i 1 - \row \i Hour \i 0 - \row \i Minute \i 0 - \row \i Second \i 0 + \header \li Field \li Default value + \row \li Year \li 1900 + \row \li Month \li 1 (January) + \row \li Day \li 1 + \row \li Hour \li 0 + \row \li Minute \li 0 + \row \li Second \li 0 \endtable For example: diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 36497c59ff..d5703e8b2a 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -547,11 +547,11 @@ void QHashData::checkSanity() differences are: \list - \i QHash provides faster lookups than QMap. (See \l{Algorithmic + \li QHash provides faster lookups than QMap. (See \l{Algorithmic Complexity} for details.) - \i When iterating over a QMap, the items are always sorted by + \li When iterating over a QMap, the items are always sorted by key. With QHash, the items are arbitrarily ordered. - \i The key type of a QMap must provide operator<(). The key + \li The key type of a QMap must provide operator<(). The key type of a QHash must provide operator==() and a global hash function called qHash() (see the related non-member functions). diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp index 78f1c44263..39ec0ed97c 100644 --- a/src/corelib/tools/qline.cpp +++ b/src/corelib/tools/qline.cpp @@ -61,8 +61,8 @@ QT_BEGIN_NAMESPACE \table \row - \o \inlineimage qline-point.png - \o \inlineimage qline-coordinates.png + \li \inlineimage qline-point.png + \li \inlineimage qline-coordinates.png \endtable The positions of the line's start and end points can be retrieved @@ -322,8 +322,8 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) \table \row - \o \inlineimage qline-point.png - \o \inlineimage qline-coordinates.png + \li \inlineimage qline-point.png + \li \inlineimage qline-coordinates.png \endtable The positions of the line's start and end points can be retrieved @@ -360,11 +360,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) \table \row - \o \inlineimage qlinef-unbounded.png - \o \inlineimage qlinef-bounded.png + \li \inlineimage qlinef-unbounded.png + \li \inlineimage qlinef-bounded.png \row - \o QLineF::UnboundedIntersection - \o QLineF::BoundedIntersection + \li QLineF::UnboundedIntersection + \li QLineF::BoundedIntersection \endtable \value NoIntersection Indicates that the lines do not intersect; @@ -795,8 +795,8 @@ qreal QLineF::angleTo(const QLineF &l) const \table \row - \o \inlineimage qlinef-angle-identicaldirection.png - \o \inlineimage qlinef-angle-oppositedirection.png + \li \inlineimage qlinef-angle-identicaldirection.png + \li \inlineimage qlinef-angle-oppositedirection.png \endtable When the lines are parallel, this function returns 0 if they have diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index e2efaa3639..b31ef3e5e9 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -65,16 +65,16 @@ const QLinkedListData QLinkedListData::shared_null = { functionality. Here's an overview: \list - \i For most purposes, QList is the right class to use. Its + \li For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory (see \l{Algorithmic Complexity} for details). It also expands to less code in your executable. - \i If you need a real linked list, with guarantees of \l{constant + \li If you need a real linked list, with guarantees of \l{constant time} insertions in the middle of the list and iterators to items rather than indexes, use QLinkedList. - \i If you want the items to occupy adjacent memory positions, + \li If you want the items to occupy adjacent memory positions, use QVector. \endlist diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index b8c938e216..263045a25d 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -340,15 +340,15 @@ void **QListData::erase(void **xi) functionality. Here's an overview: \list - \i For most purposes, QList is the right class to use. Its + \li For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory. It also expands to less code in your executable. - \i If you need a real linked list, with guarantees of \l{constant + \li If you need a real linked list, with guarantees of \l{constant time} insertions in the middle of the list and iterators to items rather than indexes, use QLinkedList. - \i If you want the items to occupy adjacent memory positions, + \li If you want the items to occupy adjacent memory positions, use QVector. \endlist diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 31f776dc2e..086ca7bd38 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -621,10 +621,10 @@ static quint16 localePrivateIndex(const QLocalePrivate *p) "language[_script][_country][.codeset][@modifier]" or "C", where: \list - \i language is a lowercase, two-letter, ISO 639 language code, - \i script is a titlecase, four-letter, ISO 15924 script code, - \i country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations), - \i and codeset and modifier are ignored. + \li language is a lowercase, two-letter, ISO 639 language code, + \li script is a titlecase, four-letter, ISO 15924 script code, + \li country is an uppercase, two- or three-letter, ISO 3166 country code (also "419" as defined by United Nations), + \li and codeset and modifier are ignored. \endlist The separator can be either underscore or a minus sign. @@ -671,11 +671,11 @@ QLocale::QLocale() country. \list - \i If the language/country pair is found in the database, it is used. - \i If the language is found but the country is not, or if the country + \li If the language/country pair is found in the database, it is used. + \li If the language is found but the country is not, or if the country is \c AnyCountry, the language is used with the most appropriate available country (for example, Germany for German), - \i If neither the language nor the country are found, QLocale + \li If neither the language nor the country are found, QLocale defaults to the default locale (see setDefault()). \endlist @@ -707,14 +707,14 @@ QLocale::QLocale(Language language, Country country) \a country. \list - \i If the language/script/country is found in the database, it is used. - \i If both \a script is AnyScript and \a country is AnyCountry, the + \li If the language/script/country is found in the database, it is used. + \li If both \a script is AnyScript and \a country is AnyCountry, the language is used with the most appropriate available script and country (for example, Germany for German), - \i If either \a script is AnyScript or \a country is AnyCountry, the + \li If either \a script is AnyScript or \a country is AnyCountry, the language is used with the first locale that matches the given \a script and \a country. - \i If neither the language nor the country are found, QLocale + \li If neither the language nor the country are found, QLocale defaults to the default locale (see setDefault()). \endlist diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index 3a386c17d6..8e90d7d94e 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -51,12 +51,12 @@ following effects: \list - \i If a QLocale object is constructed with the default constructor, + \li If a QLocale object is constructed with the default constructor, it will use the default locale's settings. - \i QString::toInt(), QString::toDouble(), etc., interpret the + \li QString::toInt(), QString::toDouble(), etc., interpret the string according to the default locale. If this fails, it falls back on the "C" locale. - \i QString::arg() uses the default locale to format a number when + \li QString::arg() uses the default locale to format a number when its position specifier in the format string contains an 'L', e.g. "%L1". \endlist @@ -69,11 +69,11 @@ of three things can happen: \list - \i If the language/country pair is found in the database, it is used. - \i If the language is found but the country is not, or if the country + \li If the language/country pair is found in the database, it is used. + \li If the language is found but the country is not, or if the country is \c AnyCountry, the language is used with the most appropriate available country (for example, Germany for German), - \i If neither the language nor the country are found, QLocale + \li If neither the language nor the country are found, QLocale defaults to the default locale (see setDefault()). \endlist diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 37d705b3e0..103d074941 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -232,11 +232,11 @@ void QMapData::dump() differences are: \list - \i QHash provides faster lookups than QMap. (See \l{Algorithmic + \li QHash provides faster lookups than QMap. (See \l{Algorithmic Complexity} for details.) - \i When iterating over a QHash, the items are arbitrarily ordered. + \li When iterating over a QHash, the items are arbitrarily ordered. With QMap, the items are always sorted by key. - \i The key type of a QHash must provide operator==() and a global + \li The key type of a QHash must provide operator==() and a global qHash(Key) function. The key type of a QMap must provide operator<() specifying a total order. \endlist diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 7ff883a99a..aeab97803d 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -99,11 +99,11 @@ QT_BEGIN_NAMESPACE \table \row - \o \inlineimage qrect-intersect.png - \o \inlineimage qrect-unite.png + \li \inlineimage qrect-intersect.png + \li \inlineimage qrect-unite.png \row - \o intersected() - \o united() + \li intersected() + \li united() \endtable The isEmpty() function returns true if left() > right() or top() > @@ -139,17 +139,17 @@ QT_BEGIN_NAMESPACE \table \row - \o \inlineimage qrect-diagram-zero.png - \o \inlineimage qrect-diagram-one.png + \li \inlineimage qrect-diagram-zero.png + \li \inlineimage qrect-diagram-one.png \row - \o Logical representation - \o One pixel wide pen + \li Logical representation + \li One pixel wide pen \row - \o \inlineimage qrect-diagram-two.png - \o \inlineimage qrect-diagram-three.png + \li \inlineimage qrect-diagram-two.png + \li \inlineimage qrect-diagram-three.png \row - \o Two pixel wide pen - \o Three pixel wide pen + \li Two pixel wide pen + \li Three pixel wide pen \endtable \section1 Coordinates @@ -1278,11 +1278,11 @@ QDebug operator<<(QDebug dbg, const QRect &r) { \table \row - \o \inlineimage qrect-intersect.png - \o \inlineimage qrect-unite.png + \li \inlineimage qrect-intersect.png + \li \inlineimage qrect-unite.png \row - \o intersected() - \o united() + \li intersected() + \li united() \endtable The isEmpty() function returns true if the rectangle's width or @@ -1318,17 +1318,17 @@ QDebug operator<<(QDebug dbg, const QRect &r) { \table \row - \o \inlineimage qrect-diagram-zero.png - \o \inlineimage qrectf-diagram-one.png + \li \inlineimage qrect-diagram-zero.png + \li \inlineimage qrectf-diagram-one.png \row - \o Logical representation - \o One pixel wide pen + \li Logical representation + \li One pixel wide pen \row - \o \inlineimage qrectf-diagram-two.png - \o \inlineimage qrectf-diagram-three.png + \li \inlineimage qrectf-diagram-two.png + \li \inlineimage qrectf-diagram-three.png \row - \o Two pixel wide pen - \o Three pixel wide pen + \li Two pixel wide pen + \li Three pixel wide pen \endtable \section1 Coordinates diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index e55144ec4c..29b3424315 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -90,21 +90,21 @@ int qFindString(const QChar *haystack, int haystackLen, int from, substrings in a text. This is useful in many contexts, e.g., \table - \row \i Validation - \i A regexp can test whether a substring meets some criteria, + \row \li Validation + \li A regexp can test whether a substring meets some criteria, e.g. is an integer or contains no whitespace. - \row \i Searching - \i A regexp provides more powerful pattern matching than + \row \li Searching + \li A regexp provides more powerful pattern matching than simple substring matching, e.g., match one of the words \e{mail}, \e{letter} or \e{correspondence}, but none of the words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc. - \row \i Search and Replace - \i A regexp can replace all occurrences of a substring with a + \row \li Search and Replace + \li A regexp can replace all occurrences of a substring with a different substring, e.g., replace all occurrences of \e{&} with \e{\&} except where the \e{&} is already followed by an \e{amp;}. - \row \i String Splitting - \i A regexp can be used to identify where a string should be + \row \li String Splitting + \li A regexp can be used to identify where a string should be split apart, e.g. splitting tab-delimited strings. \endtable @@ -127,18 +127,18 @@ int qFindString(const QChar *haystack, int haystackLen, int from, \section1 Introduction Regexps are built up from expressions, quantifiers, and - assertions. The simplest expression is a character, e.g. \bold{x} - or \bold{5}. An expression can also be a set of characters - enclosed in square brackets. \bold{[ABCD]} will match an \bold{A} - or a \bold{B} or a \bold{C} or a \bold{D}. We can write this same - expression as \bold{[A-D]}, and an experession to match any + assertions. The simplest expression is a character, e.g. \b{x} + or \b{5}. An expression can also be a set of characters + enclosed in square brackets. \b{[ABCD]} will match an \b{A} + or a \b{B} or a \b{C} or a \b{D}. We can write this same + expression as \b{[A-D]}, and an experession to match any captital letter in the English alphabet is written as - \bold{[A-Z]}. + \b{[A-Z]}. A quantifier specifies the number of occurrences of an expression - that must be matched. \bold{x{1,1}} means match one and only one - \bold{x}. \bold{x{1,5}} means match a sequence of \bold{x} - characters that contains at least one \bold{x} but no more than + that must be matched. \b{x{1,1}} means match one and only one + \b{x}. \b{x{1,5}} means match a sequence of \b{x} + characters that contains at least one \b{x} but no more than five. Note that in general regexps cannot be used to check for balanced @@ -156,35 +156,35 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Suppose we want a regexp to match integers in the range 0 to 99. At least one digit is required, so we start with the expression - \bold{[0-9]{1,1}}, which matches a single digit exactly once. This + \b{[0-9]{1,1}}, which matches a single digit exactly once. This regexp matches integers in the range 0 to 9. To match integers up to 99, increase the maximum number of occurrences to 2, so the - regexp becomes \bold{[0-9]{1,2}}. This regexp satisfies the + regexp becomes \b{[0-9]{1,2}}. This regexp satisfies the original requirement to match integers from 0 to 99, but it will also match integers that occur in the middle of strings. If we want the matched integer to be the whole string, we must use the - anchor assertions, \bold{^} (caret) and \bold{$} (dollar). When - \bold{^} is the first character in a regexp, it means the regexp - must match from the beginning of the string. When \bold{$} is the + anchor assertions, \b{^} (caret) and \b{$} (dollar). When + \b{^} is the first character in a regexp, it means the regexp + must match from the beginning of the string. When \b{$} is the last character of the regexp, it means the regexp must match to - the end of the string. The regexp becomes \bold{^[0-9]{1,2}$}. - Note that assertions, e.g. \bold{^} and \bold{$}, do not match + the end of the string. The regexp becomes \b{^[0-9]{1,2}$}. + Note that assertions, e.g. \b{^} and \b{$}, do not match characters but locations in the string. If you have seen regexps described elsewhere, they may have looked different from the ones shown here. This is because some sets of characters and some quantifiers are so common that they have been - given special symbols to represent them. \bold{[0-9]} can be - replaced with the symbol \bold{\\d}. The quantifier to match - exactly one occurrence, \bold{{1,1}}, can be replaced with the - expression itself, i.e. \bold{x{1,1}} is the same as \bold{x}. So - our 0 to 99 matcher could be written as \bold{^\\d{1,2}$}. It can - also be written \bold{^\\d\\d{0,1}$}, i.e. \e{From the start of + given special symbols to represent them. \b{[0-9]} can be + replaced with the symbol \b{\\d}. The quantifier to match + exactly one occurrence, \b{{1,1}}, can be replaced with the + expression itself, i.e. \b{x{1,1}} is the same as \b{x}. So + our 0 to 99 matcher could be written as \b{^\\d{1,2}$}. It can + also be written \b{^\\d\\d{0,1}$}, i.e. \e{From the start of the string, match a digit, followed immediately by 0 or 1 digits}. - In practice, it would be written as \bold{^\\d\\d?$}. The \bold{?} - is shorthand for the quantifier \bold{{0,1}}, i.e. 0 or 1 - occurrences. \bold{?} makes an expression optional. The regexp - \bold{^\\d\\d?$} means \e{From the beginning of the string, match + In practice, it would be written as \b{^\\d\\d?$}. The \b{?} + is shorthand for the quantifier \b{{0,1}}, i.e. 0 or 1 + occurrences. \b{?} makes an expression optional. The regexp + \b{^\\d\\d?$} means \e{From the beginning of the string, match one digit, followed immediately by 0 or 1 more digit, followed immediately by end of string}. @@ -192,45 +192,45 @@ int qFindString(const QChar *haystack, int haystackLen, int from, 'letter' \e or 'correspondence' but does not match words that contain these words, e.g., 'email', 'mailman', 'mailer', and 'letterbox', start with a regexp that matches 'mail'. Expressed - fully, the regexp is \bold{m{1,1}a{1,1}i{1,1}l{1,1}}, but because + fully, the regexp is \b{m{1,1}a{1,1}i{1,1}l{1,1}}, but because a character expression is automatically quantified by - \bold{{1,1}}, we can simplify the regexp to \bold{mail}, i.e., an + \b{{1,1}}, we can simplify the regexp to \b{mail}, i.e., an 'm' followed by an 'a' followed by an 'i' followed by an 'l'. Now - we can use the vertical bar \bold{|}, which means \bold{or}, to + we can use the vertical bar \b{|}, which means \b{or}, to include the other two words, so our regexp for matching any of the - three words becomes \bold{mail|letter|correspondence}. Match - 'mail' \bold{or} 'letter' \bold{or} 'correspondence'. While this + three words becomes \b{mail|letter|correspondence}. Match + 'mail' \b{or} 'letter' \b{or} 'correspondence'. While this regexp will match one of the three words we want to match, it will also match words we don't want to match, e.g., 'email'. To prevent the regexp from matching unwanted words, we must tell it to begin and end the match at word boundaries. First we enclose - our regexp in parentheses, \bold{(mail|letter|correspondence)}. + our regexp in parentheses, \b{(mail|letter|correspondence)}. Parentheses group expressions together, and they identify a part of the regexp that we wish to \l{capturing text}{capture}. Enclosing the expression in parentheses allows us to use it as a component in more complex regexps. It also allows us to examine which of the three words was actually matched. To force the match to begin and end on word boundaries, we enclose the regexp in - \bold{\\b} \e{word boundary} assertions: - \bold{\\b(mail|letter|correspondence)\\b}. Now the regexp means: + \b{\\b} \e{word boundary} assertions: + \b{\\b(mail|letter|correspondence)\\b}. Now the regexp means: \e{Match a word boundary, followed by the regexp in parentheses, - followed by a word boundary}. The \bold{\\b} assertion matches a + followed by a word boundary}. The \b{\\b} assertion matches a \e position in the regexp, not a \e character. A word boundary is any non-word character, e.g., a space, newline, or the beginning or ending of a string. If we want to replace ampersand characters with the HTML entity - \bold{\&}, the regexp to match is simply \bold{\&}. But this + \b{\&}, the regexp to match is simply \b{\&}. But this regexp will also match ampersands that have already been converted to HTML entities. We want to replace only ampersands that are not - already followed by \bold{amp;}. For this, we need the negative - lookahead assertion, \bold{(?!}__\bold{)}. The regexp can then be - written as \bold{\&(?!amp;)}, i.e. \e{Match an ampersand that is} - \bold{not} \e{followed by} \bold{amp;}. + already followed by \b{amp;}. For this, we need the negative + lookahead assertion, \b{(?!}__\b{)}. The regexp can then be + written as \b{\&(?!amp;)}, i.e. \e{Match an ampersand that is} + \b{not} \e{followed by} \b{amp;}. If we want to count all the occurrences of 'Eric' and 'Eirik' in a - string, two valid solutions are \bold{\\b(Eric|Eirik)\\b} and - \bold{\\bEi?ri[ck]\\b}. The word boundary assertion '\\b' is + string, two valid solutions are \b{\\b(Eric|Eirik)\\b} and + \b{\\bEi?ri[ck]\\b}. The word boundary assertion '\\b' is required to avoid matching words that contain either name, e.g. 'Ericsson'. Note that the second regexp matches more spellings than we want: 'Eric', 'Erik', 'Eiric' and 'Eirik'. @@ -242,52 +242,52 @@ int qFindString(const QChar *haystack, int haystackLen, int from, \section1 Characters and Abbreviations for Sets of Characters \table - \header \i Element \i Meaning - \row \i \bold{c} - \i A character represents itself unless it has a special - regexp meaning. e.g. \bold{c} matches the character \e c. - \row \i \bold{\\c} - \i A character that follows a backslash matches the character + \header \li Element \li Meaning + \row \li \b{c} + \li A character represents itself unless it has a special + regexp meaning. e.g. \b{c} matches the character \e c. + \row \li \b{\\c} + \li A character that follows a backslash matches the character itself, except as specified below. e.g., To match a literal - caret at the beginning of a string, write \bold{\\^}. - \row \i \bold{\\a} - \i Matches the ASCII bell (BEL, 0x07). - \row \i \bold{\\f} - \i Matches the ASCII form feed (FF, 0x0C). - \row \i \bold{\\n} - \i Matches the ASCII line feed (LF, 0x0A, Unix newline). - \row \i \bold{\\r} - \i Matches the ASCII carriage return (CR, 0x0D). - \row \i \bold{\\t} - \i Matches the ASCII horizontal tab (HT, 0x09). - \row \i \bold{\\v} - \i Matches the ASCII vertical tab (VT, 0x0B). - \row \i \bold{\\x\e{hhhh}} - \i Matches the Unicode character corresponding to the + caret at the beginning of a string, write \b{\\^}. + \row \li \b{\\a} + \li Matches the ASCII bell (BEL, 0x07). + \row \li \b{\\f} + \li Matches the ASCII form feed (FF, 0x0C). + \row \li \b{\\n} + \li Matches the ASCII line feed (LF, 0x0A, Unix newline). + \row \li \b{\\r} + \li Matches the ASCII carriage return (CR, 0x0D). + \row \li \b{\\t} + \li Matches the ASCII horizontal tab (HT, 0x09). + \row \li \b{\\v} + \li Matches the ASCII vertical tab (VT, 0x0B). + \row \li \b{\\x\e{hhhh}} + \li Matches the Unicode character corresponding to the hexadecimal number \e{hhhh} (between 0x0000 and 0xFFFF). - \row \i \bold{\\0\e{ooo}} (i.e., \\zero \e{ooo}) - \i matches the ASCII/Latin1 character for the octal number + \row \li \b{\\0\e{ooo}} (i.e., \\zero \e{ooo}) + \li matches the ASCII/Latin1 character for the octal number \e{ooo} (between 0 and 0377). - \row \i \bold{. (dot)} - \i Matches any character (including newline). - \row \i \bold{\\d} - \i Matches a digit (QChar::isDigit()). - \row \i \bold{\\D} - \i Matches a non-digit. - \row \i \bold{\\s} - \i Matches a whitespace character (QChar::isSpace()). - \row \i \bold{\\S} - \i Matches a non-whitespace character. - \row \i \bold{\\w} - \i Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_'). - \row \i \bold{\\W} - \i Matches a non-word character. - \row \i \bold{\\\e{n}} - \i The \e{n}-th \l backreference, e.g. \\1, \\2, etc. + \row \li \b{. (dot)} + \li Matches any character (including newline). + \row \li \b{\\d} + \li Matches a digit (QChar::isDigit()). + \row \li \b{\\D} + \li Matches a non-digit. + \row \li \b{\\s} + \li Matches a whitespace character (QChar::isSpace()). + \row \li \b{\\S} + \li Matches a non-whitespace character. + \row \li \b{\\w} + \li Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_'). + \row \li \b{\\W} + \li Matches a non-word character. + \row \li \b{\\\e{n}} + \li The \e{n}-th \l backreference, e.g. \\1, \\2, etc. \endtable - \bold{Note:} The C++ compiler transforms backslashes in strings. - To include a \bold{\\} in a regexp, enter it twice, i.e. \c{\\}. + \b{Note:} The C++ compiler transforms backslashes in strings. + To include a \b{\\} in a regexp, enter it twice, i.e. \c{\\}. To match the backslash character itself, enter it four times, i.e. \c{\\\\}. @@ -301,24 +301,24 @@ int qFindString(const QChar *haystack, int haystackLen, int from, characters do not have special meanings in square brackets. \table - \row \i \bold{^} + \row \li \b{^} - \i The caret negates the character set if it occurs as the + \li The caret negates the character set if it occurs as the first character (i.e. immediately after the opening square - bracket). \bold{[abc]} matches 'a' or 'b' or 'c', but - \bold{[^abc]} matches anything \e but 'a' or 'b' or 'c'. + bracket). \b{[abc]} matches 'a' or 'b' or 'c', but + \b{[^abc]} matches anything \e but 'a' or 'b' or 'c'. - \row \i \bold{-} + \row \li \b{-} - \i The dash indicates a range of characters. \bold{[W-Z]} + \li The dash indicates a range of characters. \b{[W-Z]} matches 'W' or 'X' or 'Y' or 'Z'. \endtable Using the predefined character set abbreviations is more portable than using character ranges across platforms and languages. For - example, \bold{[0-9]} matches a digit in Western alphabets but - \bold{\\d} matches a digit in \e any alphabet. + example, \b{[0-9]} matches a digit in Western alphabets but + \b{\\d} matches a digit in \e any alphabet. Note: In other regexp documentation, sets of characters are often called "character classes". @@ -327,64 +327,64 @@ int qFindString(const QChar *haystack, int haystackLen, int from, \section1 Quantifiers By default, an expression is automatically quantified by - \bold{{1,1}}, i.e. it should occur exactly once. In the following - list, \bold{\e {E}} stands for expression. An expression is a + \b{{1,1}}, i.e. it should occur exactly once. In the following + list, \b{\e {E}} stands for expression. An expression is a character, or an abbreviation for a set of characters, or a set of characters in square brackets, or an expression in parentheses. \table - \row \i \bold{\e {E}?} + \row \li \b{\e {E}?} - \i Matches zero or one occurrences of \e E. This quantifier + \li Matches zero or one occurrences of \e E. This quantifier means \e{The previous expression is optional}, because it - will match whether or not the expression is found. \bold{\e - {E}?} is the same as \bold{\e {E}{0,1}}. e.g., \bold{dents?} + will match whether or not the expression is found. \b{\e + {E}?} is the same as \b{\e {E}{0,1}}. e.g., \b{dents?} matches 'dent' or 'dents'. - \row \i \bold{\e {E}+} + \row \li \b{\e {E}+} - \i Matches one or more occurrences of \e E. \bold{\e {E}+} is - the same as \bold{\e {E}{1,}}. e.g., \bold{0+} matches '0', + \li Matches one or more occurrences of \e E. \b{\e {E}+} is + the same as \b{\e {E}{1,}}. e.g., \b{0+} matches '0', '00', '000', etc. - \row \i \bold{\e {E}*} + \row \li \b{\e {E}*} - \i Matches zero or more occurrences of \e E. It is the same - as \bold{\e {E}{0,}}. The \bold{*} quantifier is often used - in error where \bold{+} should be used. For example, if - \bold{\\s*$} is used in an expression to match strings that + \li Matches zero or more occurrences of \e E. It is the same + as \b{\e {E}{0,}}. The \b{*} quantifier is often used + in error where \b{+} should be used. For example, if + \b{\\s*$} is used in an expression to match strings that end in whitespace, it will match every string because - \bold{\\s*$} means \e{Match zero or more whitespaces followed + \b{\\s*$} means \e{Match zero or more whitespaces followed by end of string}. The correct regexp to match strings that have at least one trailing whitespace character is - \bold{\\s+$}. + \b{\\s+$}. - \row \i \bold{\e {E}{n}} + \row \li \b{\e {E}{n}} - \i Matches exactly \e n occurrences of \e E. \bold{\e {E}{n}} + \li Matches exactly \e n occurrences of \e E. \b{\e {E}{n}} is the same as repeating \e E \e n times. For example, - \bold{x{5}} is the same as \bold{xxxxx}. It is also the same - as \bold{\e {E}{n,n}}, e.g. \bold{x{5,5}}. + \b{x{5}} is the same as \b{xxxxx}. It is also the same + as \b{\e {E}{n,n}}, e.g. \b{x{5,5}}. - \row \i \bold{\e {E}{n,}} - \i Matches at least \e n occurrences of \e E. + \row \li \b{\e {E}{n,}} + \li Matches at least \e n occurrences of \e E. - \row \i \bold{\e {E}{,m}} - \i Matches at most \e m occurrences of \e E. \bold{\e {E}{,m}} - is the same as \bold{\e {E}{0,m}}. + \row \li \b{\e {E}{,m}} + \li Matches at most \e m occurrences of \e E. \b{\e {E}{,m}} + is the same as \b{\e {E}{0,m}}. - \row \i \bold{\e {E}{n,m}} - \i Matches at least \e n and at most \e m occurrences of \e E. + \row \li \b{\e {E}{n,m}} + \li Matches at least \e n and at most \e m occurrences of \e E. \endtable To apply a quantifier to more than just the preceding character, use parentheses to group characters together in an expression. For - example, \bold{tag+} matches a 't' followed by an 'a' followed by - at least one 'g', whereas \bold{(tag)+} matches at least one + example, \b{tag+} matches a 't' followed by an 'a' followed by + at least one 'g', whereas \b{(tag)+} matches at least one occurrence of 'tag'. Note: Quantifiers are normally "greedy". They always match as much - text as they can. For example, \bold{0+} matches the first zero it + text as they can. For example, \b{0+} matches the first zero it finds and all the consecutive zeros after the first zero. Applied to '20005', it matches'2\underline{000}5'. Quantifiers can be made non-greedy, see setMinimal(). @@ -395,10 +395,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Parentheses allow us to group elements together so that we can quantify and capture them. For example if we have the expression - \bold{mail|letter|correspondence} that matches a string we know + \b{mail|letter|correspondence} that matches a string we know that \e one of the words matched but not which one. Using parentheses allows us to "capture" whatever is matched within - their bounds, so if we used \bold{(mail|letter|correspondence)} + their bounds, so if we used \b{(mail|letter|correspondence)} and matched this regexp against the string "I sent you some email" we can use the cap() or capturedTexts() functions to extract the matched characters, in this case 'mail'. @@ -406,14 +406,14 @@ int qFindString(const QChar *haystack, int haystackLen, int from, We can use captured text within the regexp itself. To refer to the captured text we use \e backreferences which are indexed from 1, the same as for cap(). For example we could search for duplicate - words in a string using \bold{\\b(\\w+)\\W+\\1\\b} which means match a + words in a string using \b{\\b(\\w+)\\W+\\1\\b} which means match a word boundary followed by one or more word characters followed by one or more non-word characters followed by the same text as the first parenthesized expression followed by a word boundary. If we want to use parentheses purely for grouping and not for capturing we can use the non-capturing syntax, e.g. - \bold{(?:green|blue)}. Non-capturing parentheses begin '(?:' and + \b{(?:green|blue)}. Non-capturing parentheses begin '(?:' and end ')'. In this example we match either 'green' or 'blue' but we do not capture the match so we only know whether or not we matched but not which color we actually found. Using non-capturing @@ -424,9 +424,9 @@ int qFindString(const QChar *haystack, int haystackLen, int from, \target greedy quantifiers - For historical reasons, quantifiers (e.g. \bold{*}) that apply to + For historical reasons, quantifiers (e.g. \b{*}) that apply to capturing parentheses are more "greedy" than other quantifiers. - For example, \bold{a*(a*)} will match "aaa" with cap(1) == "aaa". + For example, \b{a*(a*)} will match "aaa" with cap(1) == "aaa". This behavior is different from what other regexp engines do (notably, Perl). To obtain a more intuitive capturing behavior, specify QRegExp::RegExp2 to the QRegExp constructor or call @@ -444,54 +444,54 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Assertions make some statement about the text at the point where they occur in the regexp but they do not match any characters. In - the following list \bold{\e {E}} stands for any expression. + the following list \b{\e {E}} stands for any expression. \table - \row \i \bold{^} - \i The caret signifies the beginning of the string. If you + \row \li \b{^} + \li The caret signifies the beginning of the string. If you wish to match a literal \c{^} you must escape it by - writing \c{\\^}. For example, \bold{^#include} will only + writing \c{\\^}. For example, \b{^#include} will only match strings which \e begin with the characters '#include'. (When the caret is the first character of a character set it has a special meaning, see \link #sets-of-characters Sets of Characters \endlink.) - \row \i \bold{$} - \i The dollar signifies the end of the string. For example - \bold{\\d\\s*$} will match strings which end with a digit + \row \li \b{$} + \li The dollar signifies the end of the string. For example + \b{\\d\\s*$} will match strings which end with a digit optionally followed by whitespace. If you wish to match a literal \c{$} you must escape it by writing \c{\\$}. - \row \i \bold{\\b} - \i A word boundary. For example the regexp - \bold{\\bOK\\b} means match immediately after a word + \row \li \b{\\b} + \li A word boundary. For example the regexp + \b{\\bOK\\b} means match immediately after a word boundary (e.g. start of string or whitespace) the letter 'O' then the letter 'K' immediately before another word boundary (e.g. end of string or whitespace). But note that the assertion does not actually match any whitespace so if we - write \bold{(\\bOK\\b)} and we have a match it will only + write \b{(\\bOK\\b)} and we have a match it will only contain 'OK' even if the string is "It's \underline{OK} now". - \row \i \bold{\\B} - \i A non-word boundary. This assertion is true wherever - \bold{\\b} is false. For example if we searched for - \bold{\\Bon\\B} in "Left on" the match would fail (space + \row \li \b{\\B} + \li A non-word boundary. This assertion is true wherever + \b{\\b} is false. For example if we searched for + \b{\\Bon\\B} in "Left on" the match would fail (space and end of string aren't non-word boundaries), but it would match in "t\underline{on}ne". - \row \i \bold{(?=\e E)} - \i Positive lookahead. This assertion is true if the + \row \li \b{(?=\e E)} + \li Positive lookahead. This assertion is true if the expression matches at this point in the regexp. For example, - \bold{const(?=\\s+char)} matches 'const' whenever it is + \b{const(?=\\s+char)} matches 'const' whenever it is followed by 'char', as in 'static \underline{const} char *'. - (Compare with \bold{const\\s+char}, which matches 'static + (Compare with \b{const\\s+char}, which matches 'static \underline{const char} *'.) - \row \i \bold{(?!\e E)} - \i Negative lookahead. This assertion is true if the + \row \li \b{(?!\e E)} + \li Negative lookahead. This assertion is true if the expression does not match at this point in the regexp. For - example, \bold{const(?!\\s+char)} matches 'const' \e except + example, \b{const(?!\\s+char)} matches 'const' \e except when it is followed by 'char'. \endtable @@ -505,17 +505,17 @@ int qFindString(const QChar *haystack, int haystackLen, int from, simpler than full regexps and has only four features: \table - \row \i \bold{c} - \i Any character represents itself apart from those mentioned - below. Thus \bold{c} matches the character \e c. - \row \i \bold{?} - \i Matches any single character. It is the same as - \bold{.} in full regexps. - \row \i \bold{*} - \i Matches zero or more of any characters. It is the - same as \bold{.*} in full regexps. - \row \i \bold{[...]} - \i Sets of characters can be represented in square brackets, + \row \li \b{c} + \li Any character represents itself apart from those mentioned + below. Thus \b{c} matches the character \e c. + \row \li \b{?} + \li Matches any single character. It is the same as + \b{.} in full regexps. + \row \li \b{*} + \li Matches zero or more of any characters. It is the + same as \b{.*} in full regexps. + \row \li \b{[...]} + \li Sets of characters can be represented in square brackets, similar to full regexps. Within the character class, like outside, backslash has no special meaning. \endtable @@ -525,7 +525,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, wildcard. For example if we are in wildcard mode and have strings which - contain filenames we could identify HTML files with \bold{*.html}. + contain filenames we could identify HTML files with \b{*.html}. This will match zero or more characters followed by a dot followed by 'h', 't', 'm' and 'l'. @@ -553,7 +553,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, (but see the \l{greedy quantifiers}{note above}). Non-greedy matching cannot be applied to individual quantifiers, but can be applied to all the quantifiers in the pattern. For example, to - match the Perl regexp \bold{ro+?m} requires: + match the Perl regexp \b{ro+?m} requires: \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 2 @@ -562,7 +562,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Perl's \c{/g} option can be emulated using a \l{#cap_in_a_loop}{loop}. - In QRegExp \bold{.} matches any character, therefore all QRegExp + In QRegExp \b{.} matches any character, therefore all QRegExp regexps have the equivalent of Perl's \c{/s} option. QRegExp does not have an equivalent to Perl's \c{/m} option, but this can be emulated in various ways for example by splitting the input @@ -598,7 +598,7 @@ int qFindString(const QChar *haystack, int haystackLen, int from, to Perl's split and join functions. Note: because C++ transforms \\'s they must be written \e twice in - code, e.g. \bold{\\b} must be written \bold{\\\\b}. + code, e.g. \b{\\b} must be written \b{\\\\b}. \target code-examples \section1 Code Examples @@ -670,10 +670,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, Wildcard matching can be convenient because of its simplicity, but any wildcard regexp can be defined using full regexps, e.g. - \bold{.*\\.html$}. Notice that we can't match both \c .html and \c - .htm files with a wildcard unless we use \bold{*.htm*} which will + \b{.*\\.html$}. Notice that we can't match both \c .html and \c + .htm files with a wildcard unless we use \b{*.htm*} which will also match 'test.html.bak'. A full regexp gives us the precision - we need, \bold{.*\\.html?$}. + we need, \b{.*\\.html?$}. QRegExp can match case insensitively using setCaseSensitivity(), and can use non-greedy matching, see setMinimal(). By @@ -3898,7 +3898,7 @@ static void invalidateEngine(QRegExpPrivate *priv) \enum QRegExp::CaretMode The CaretMode enum defines the different meanings of the caret - (\bold{^}) in a regular expression. The possible values are: + (\b{^}) in a regular expression. The possible values are: \value CaretAtZero The caret corresponds to index 0 in the searched string. @@ -4065,11 +4065,11 @@ bool QRegExp::isEmpty() const Returns true if the regular expression is valid; otherwise returns false. An invalid regular expression never matches. - The pattern \bold{[a-z} is an example of an invalid pattern, since + The pattern \b{[a-z} is an example of an invalid pattern, since it lacks a closing square bracket. Note that the validity of a regexp may also depend on the setting - of the wildcard flag, for example \bold{*.html} is a valid + of the wildcard flag, for example \b{*.html} is a valid wildcard regexp but an invalid full regexp. \sa errorString() @@ -4124,7 +4124,7 @@ Qt::CaseSensitivity QRegExp::caseSensitivity() const /*! Sets case sensitive matching to \a cs. - If \a cs is Qt::CaseSensitive, \bold{\\.txt$} matches + If \a cs is Qt::CaseSensitive, \b{\\.txt$} matches \c{readme.txt} but not \c{README.TXT}. \sa setPatternSyntax(), setPattern(), setMinimal() @@ -4153,7 +4153,7 @@ QRegExp::PatternSyntax QRegExp::patternSyntax() const QRegExp::RegExp. Setting \a syntax to QRegExp::Wildcard enables simple shell-like - \l{wildcard matching}. For example, \bold{r*.txt} matches the + \l{wildcard matching}. For example, \b{r*.txt} matches the string \c{readme.txt} in wildcard mode, but does not match \c{readme}. @@ -4188,13 +4188,13 @@ bool QRegExp::isMinimal() const For example, suppose we have the input string "We must be bold, very bold!" and the pattern - \bold{.*}. With the default greedy (maximal) matching, + \b{.*}. With the default greedy (maximal) matching, the match is "We must be \underline{bold, very bold}!". But with minimal (non-greedy) matching, the first match is: "We must be \underline{bold}, very bold!" and the second match is "We must be bold, very \underline{bold}!". In practice we might use the pattern - \bold{[^<]*\} instead, although this will still fail for + \b{[^<]*\} instead, although this will still fail for nested tags. \sa setCaseSensitivity() @@ -4215,7 +4215,7 @@ void QRegExp::setMinimal(bool minimal) in the start of string and end of string anchors, except that it sets matchedLength() differently. - For example, if the regular expression is \bold{blue}, then + For example, if the regular expression is \b{blue}, then exactMatch() returns true only for input \c blue. For inputs \c bluebell, \c blutak and \c lightblue, exactMatch() returns false and matchedLength() will return 4, 3 and 0 respectively. @@ -4247,7 +4247,7 @@ bool QRegExp::exactMatch(const QString &str) const Returns the position of the first match, or -1 if there was no match. - The \a caretMode parameter can be used to instruct whether \bold{^} + The \a caretMode parameter can be used to instruct whether \b{^} should match at index 0 or at \a offset. You might prefer to use QString::indexOf(), QString::contains(), @@ -4286,7 +4286,7 @@ int QRegExp::indexIn(const QString &str, int offset, CaretMode caretMode) const Returns the position of the first match, or -1 if there was no match. - The \a caretMode parameter can be used to instruct whether \bold{^} + The \a caretMode parameter can be used to instruct whether \b{^} should match at index 0 or at \a offset. Although const, this function sets matchedLength(), @@ -4371,7 +4371,7 @@ int QRegExp::captureCount() const Some regexps can match an indeterminate number of times. For example if the input string is "Offsets: 12 14 99 231 7" and the - regexp, \c{rx}, is \bold{(\\d+)+}, we would hope to get a list of + regexp, \c{rx}, is \b{(\\d+)+}, we would hope to get a list of all the numbers matched. However, after calling \c{rx.indexIn(str)}, capturedTexts() will return the list ("12", "12"), i.e. the entire match was "12" and the first subexpression diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp index b6bf525fb9..5ecca89229 100644 --- a/src/corelib/tools/qscopedpointer.cpp +++ b/src/corelib/tools/qscopedpointer.cpp @@ -89,10 +89,10 @@ QT_BEGIN_NAMESPACE The following custom cleanup handlers exist: \list - \i QScopedPointerDeleter - the default, deletes the pointer using \c delete - \i QScopedPointerArrayDeleter - deletes the pointer using \c{delete []}. Use + \li QScopedPointerDeleter - the default, deletes the pointer using \c delete + \li QScopedPointerArrayDeleter - deletes the pointer using \c{delete []}. Use this handler for pointers that were allocated with \c{new []}. - \i QScopedPointerPodDeleter - deletes the pointer using \c{free()}. Use this + \li QScopedPointerPodDeleter - deletes the pointer using \c{free()}. Use this handler for pointers that were allocated with \c{malloc()}. \endlist diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp index 6250745400..ffc8ac601d 100644 --- a/src/corelib/tools/qshareddata.cpp +++ b/src/corelib/tools/qshareddata.cpp @@ -86,10 +86,10 @@ QT_BEGIN_NAMESPACE \list - \o Define the class \c Employee to have a single data member of + \li Define the class \c Employee to have a single data member of type \c {QSharedDataPointer}. - \o Define the \c EmployeeData class derived from \l QSharedData to + \li Define the \c EmployeeData class derived from \l QSharedData to contain all the data members you would normally have put in the \c Employee class. diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp index 4c94f899e7..b276d2d2e0 100644 --- a/src/corelib/tools/qsize.cpp +++ b/src/corelib/tools/qsize.cpp @@ -186,10 +186,10 @@ void QSize::transpose() height, according to the specified \a mode: \list - \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). - \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle + \li If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). + \li If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle as large as possible inside (\a width, \a height), preserving the aspect ratio. - \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle + \li If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle as small as possible outside (\a width, \a height), preserving the aspect ratio. \endlist @@ -614,10 +614,10 @@ void QSizeF::transpose() height, according to the specified \a mode. \list - \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). - \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle + \li If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). + \li If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle as large as possible inside (\a width, \a height), preserving the aspect ratio. - \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle + \li If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle as small as possible outside (\a width, \a height), preserving the aspect ratio. \endlist diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index bf50159de2..45ccfb8aea 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -606,12 +606,12 @@ const QString::Null QString::null = { }; toLatin1(), toUtf8(), and toLocal8Bit(). \list - \o toAscii() returns a Latin-1 (ISO 8859-1) encoded 8-bit string. - \o toLatin1() returns a Latin-1 (ISO 8859-1) encoded 8-bit string. - \o toUtf8() returns a UTF-8 encoded 8-bit string. UTF-8 is a + \li toAscii() returns a Latin-1 (ISO 8859-1) encoded 8-bit string. + \li toLatin1() returns a Latin-1 (ISO 8859-1) encoded 8-bit string. + \li toUtf8() returns a UTF-8 encoded 8-bit string. UTF-8 is a superset of US-ASCII (ANSI X3.4-1986) that supports the entire Unicode character set through multibyte sequences. - \o toLocal8Bit() returns an 8-bit string using the system's local + \li toLocal8Bit() returns an 8-bit string using the system's local encoding. \endlist @@ -629,9 +629,9 @@ const QString::Null QString::null = { }; conversions by defining the following two preprocessor symbols: \list - \o \c QT_NO_CAST_FROM_ASCII disables automatic conversions from + \li \c QT_NO_CAST_FROM_ASCII disables automatic conversions from C string literals and pointers to Unicode. - \o \c QT_NO_CAST_TO_ASCII disables automatic conversion from QString + \li \c QT_NO_CAST_TO_ASCII disables automatic conversion from QString to C strings. \endlist @@ -655,10 +655,10 @@ const QString::Null QString::null = { }; \table 100 % \header - \o Note for C Programmers + \li Note for C Programmers \row - \o + \li Due to C++'s type system and the fact that QString is \l{implicitly shared}, QStrings may be treated like \c{int}s or other basic types. For example: @@ -697,12 +697,12 @@ const QString::Null QString::null = { }; following: \table - \header \o Format \o Meaning - \row \o \c e \o format as [-]9.9e[+|-]999 - \row \o \c E \o format as [-]9.9E[+|-]999 - \row \o \c f \o format as [-]9.9 - \row \o \c g \o use \c e or \c f format, whichever is the most concise - \row \o \c G \o use \c E or \c f format, whichever is the most concise + \header \li Format \li Meaning + \row \li \c e \li format as [-]9.9e[+|-]999 + \row \li \c E \li format as [-]9.9E[+|-]999 + \row \li \c f \li format as [-]9.9 + \row \li \c g \li use \c e or \c f format, whichever is the most concise + \row \li \c G \li use \c E or \c f format, whichever is the most concise \endtable A \e precision is also specified with the argument \e format. For @@ -2789,7 +2789,7 @@ struct QStringCapture \snippet doc/src/snippets/qstring/main.cpp 42 For regular expressions containing \l{capturing parentheses}, - occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are replaced + occurrences of \b{\\1}, \b{\\2}, ..., in \a after are replaced with \a{rx}.cap(1), cap(2), ... \snippet doc/src/snippets/qstring/main.cpp 43 @@ -6059,7 +6059,7 @@ QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivit \snippet doc/src/snippets/qstring/main.cpp 60 Here's a third example where we use a zero-length assertion, - \bold{\\b} (word boundary), to split the string into an + \b{\\b} (word boundary), to split the string into an alternating sequence of non-word and word tokens: \snippet doc/src/snippets/qstring/main.cpp 61 diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index a352045a7d..b4ec0c6498 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -342,7 +342,7 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QString &b \snippet doc/src/snippets/qstringlist/main.cpp 14 For regular expressions that contain \l{capturing parentheses}, - occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are + occurrences of \b{\\1}, \b{\\2}, ..., in \a after are replaced with \a{rx}.cap(1), \a{rx}.cap(2), ... For example: diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index 1a0579a077..e1dc2bee9a 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -69,13 +69,13 @@ structure. The main differences between the two classes are: \list - \o QVarLengthArray's API is much more low-level. It provides no + \li QVarLengthArray's API is much more low-level. It provides no iterators and lacks much of QVector's functionality. - \o QVarLengthArray doesn't initialize the memory if the value is + \li QVarLengthArray doesn't initialize the memory if the value is a basic type. (QVector always does.) - \o QVector uses \l{implicit sharing} as a memory optimization. + \li QVector uses \l{implicit sharing} as a memory optimization. QVarLengthArray doesn't provide that feature; however, it usually produces slightly better performance due to reduced overhead, especially in tight loops. diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index 3efe695559..75c219bbc9 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -108,21 +108,21 @@ int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive similar functionality. Here's an overview: \list - \i For most purposes, QList is the right class to use. Operations + \li For most purposes, QList is the right class to use. Operations like prepend() and insert() are usually faster than with QVector because of the way QList stores its items in memory (see \l{Algorithmic Complexity} for details), and its index-based API is more convenient than QLinkedList's iterator-based API. It also expands to less code in your executable. - \i If you need a real linked list, with guarantees of \l{constant + \li If you need a real linked list, with guarantees of \l{constant time} insertions in the middle of the list and iterators to items rather than indexes, use QLinkedList. - \i If you want the items to occupy adjacent memory positions, or + \li If you want the items to occupy adjacent memory positions, or if your items are larger than a pointer and you want to avoid the overhead of allocating them on the heap individually at insertion time, then use QVector. - \i If you want a low-level variable-size array, QVarLengthArray + \li If you want a low-level variable-size array, QVarLengthArray may be sufficient. \endlist diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index d6bdc19d51..8863766f40 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -331,10 +331,10 @@ QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &c messages (MessageType) that can occur on the bus: \list - \o Method calls - \o Method return values - \o Signal emissions - \o Error codes + \li Method calls + \li Method return values + \li Signal emissions + \li Error codes \endlist Objects of this type are created with the static createError(), diff --git a/src/dbus/qdbuspendingreply.cpp b/src/dbus/qdbuspendingreply.cpp index 78b64c4772..b9694ca205 100644 --- a/src/dbus/qdbuspendingreply.cpp +++ b/src/dbus/qdbuspendingreply.cpp @@ -60,9 +60,9 @@ important differences: \list - \o QDBusReply accepts exactly one return type, whereas + \li QDBusReply accepts exactly one return type, whereas QDBusPendingReply can have from 1 to 8 types - \o QDBusReply only works on already completed replies, whereas + \li QDBusReply only works on already completed replies, whereas QDBusPendingReply allows one to wait for replies from pending calls \endlist diff --git a/src/dbus/qdbusservicewatcher.cpp b/src/dbus/qdbusservicewatcher.cpp index 749d68fad5..d45fa8b8ca 100644 --- a/src/dbus/qdbusservicewatcher.cpp +++ b/src/dbus/qdbusservicewatcher.cpp @@ -153,9 +153,9 @@ void QDBusServiceWatcherPrivate::removeService(const QString &service) modes: \list - \o Watching for service registration only. - \o Watching for service unregistration only. - \o Watching for any kind of service ownership change (the default mode). + \li Watching for service registration only. + \li Watching for service unregistration only. + \li Watching for any kind of service ownership change (the default mode). \endlist Besides being created or deleted, services may change owners without a diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp index 71edee1b2b..bed07692b8 100644 --- a/src/dbus/qdbusutil.cpp +++ b/src/dbus/qdbusutil.cpp @@ -348,11 +348,11 @@ namespace QDBusUtil Valid interface names must: \list - \o not be empty - \o not exceed 255 characters in length - \o be composed of dot-separated string components that contain only ASCII letters, digits + \li not be empty + \li not exceed 255 characters in length + \li be composed of dot-separated string components that contain only ASCII letters, digits and the underscore ("_") character - \o contain at least two such components + \li contain at least two such components \endlist */ bool isValidInterfaceName(const QString& ifaceName) @@ -408,11 +408,11 @@ namespace QDBusUtil A valid bus name is either a valid unique connection name or follows the rules: \list - \o is not empty - \o does not exceed 255 characters in length - \o be composed of dot-separated string components that contain only ASCII letters, digits, + \li is not empty + \li does not exceed 255 characters in length + \li be composed of dot-separated string components that contain only ASCII letters, digits, hyphens or underscores ("_"), but don't start with a digit - \o contains at least two such elements + \li contains at least two such elements \endlist \sa isValidUniqueConnectionName() @@ -481,10 +481,10 @@ namespace QDBusUtil Valid object paths follow the rules: \list - \o start with the slash character ("/") - \o do not end in a slash, unless the path is just the initial slash - \o do not contain any two slashes in sequence - \o contain slash-separated parts, each of which is composed of ASCII letters, digits and + \li start with the slash character ("/") + \li do not end in a slash, unless the path is just the initial slash + \li do not contain any two slashes in sequence + \li contain slash-separated parts, each of which is composed of ASCII letters, digits and underscores ("_") \endlist */ diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index b7e9275669..aa47616161 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -77,10 +77,10 @@ QT_BEGIN_NAMESPACE braille displays. Clients and servers communicate in the following way: \list - \o \e{AT Servers} notify the clients about events through calls to the + \li \e{AT Servers} notify the clients about events through calls to the updateAccessibility() function. - \o \e{AT Clients} request information about the objects in the server. + \li \e{AT Clients} request information about the objects in the server. The QAccessibleInterface class is the core interface, and encapsulates this information in a pure virtual API. Implementations of the interface are provided by Qt through the queryAccessibleInterface() API. @@ -748,12 +748,12 @@ QAccessibleInterface *QAccessibleEvent::accessibleInterface() const The AT client uses three basic concepts to acquire information about any accessible object in an application: \list - \i \e Properties The client can read information about + \li \e Properties The client can read information about accessible objects. In some cases the client can also modify these properties; such as text in a line edit. - \i \e Actions The client can invoke actions like pressing a button + \li \e Actions The client can invoke actions like pressing a button or . - \i \e{Relationships and Navigation} The client can traverse from one + \li \e{Relationships and Navigation} The client can traverse from one accessible object to another, using the relationships between objects. \endlist diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp index db3028b371..d3dafb8820 100644 --- a/src/gui/accessible/qaccessible2.cpp +++ b/src/gui/accessible/qaccessible2.cpp @@ -371,14 +371,14 @@ QT_BEGIN_NAMESPACE In general you should use one of the predefined action names, unless describing an action that does not fit these: \table - \header \o Action name \o Description - \row \o \l checkAction() \o checks the item (checkbox, radio button, ...) - \row \o \l decreaseAction() \o decrease the value of the accessible (e.g. spinbox) - \row \o \l increaseAction() \o increase the value of the accessible (e.g. spinbox) - \row \o \l pressAction() \o press or click or activate the accessible (should correspont to clicking the object with the mouse) - \row \o \l setFocusAction() \o set the focus to this accessible - \row \o \l showMenuAction() \o show a context menu, corresponds to right-clicks - \row \o \l uncheckAction() \o uncheck the item (checkbox, radio button, ...) + \header \li Action name \li Description + \row \li \l checkAction() \li checks the item (checkbox, radio button, ...) + \row \li \l decreaseAction() \li decrease the value of the accessible (e.g. spinbox) + \row \li \l increaseAction() \li increase the value of the accessible (e.g. spinbox) + \row \li \l pressAction() \li press or click or activate the accessible (should correspont to clicking the object with the mouse) + \row \li \l setFocusAction() \li set the focus to this accessible + \row \li \l showMenuAction() \li show a context menu, corresponds to right-clicks + \row \li \l uncheckAction() \li uncheck the item (checkbox, radio button, ...) \endtable In order to invoke the action, \l doAction() is called with an action name. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 5b23dbf4dc..6ce08d93cc 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -327,17 +327,17 @@ bool QImageData::checkForAlphaPixels() const formats: \table - \header \o Format \o Description \o Qt's support - \row \o BMP \o Windows Bitmap \o Read/write - \row \o GIF \o Graphic Interchange Format (optional) \o Read - \row \o JPG \o Joint Photographic Experts Group \o Read/write - \row \o JPEG \o Joint Photographic Experts Group \o Read/write - \row \o PNG \o Portable Network Graphics \o Read/write - \row \o PBM \o Portable Bitmap \o Read - \row \o PGM \o Portable Graymap \o Read - \row \o PPM \o Portable Pixmap \o Read/write - \row \o XBM \o X11 Bitmap \o Read/write - \row \o XPM \o X11 Pixmap \o Read/write + \header \li Format \li Description \li Qt's support + \row \li BMP \li Windows Bitmap \li Read/write + \row \li GIF \li Graphic Interchange Format (optional) \li Read + \row \li JPG \li Joint Photographic Experts Group \li Read/write + \row \li JPEG \li Joint Photographic Experts Group \li Read/write + \row \li PNG \li Portable Network Graphics \li Read/write + \row \li PBM \li Portable Bitmap \li Read + \row \li PGM \li Portable Graymap \li Read + \row \li PPM \li Portable Pixmap \li Read/write + \row \li XBM \li X11 Bitmap \li Read/write + \row \li XPM \li X11 Pixmap \li Read/write \endtable \section1 Image Information @@ -347,11 +347,11 @@ bool QImageData::checkForAlphaPixels() const \table \header - \o \o Available Functions + \li \li Available Functions \row - \o Geometry - \o + \li Geometry + \li The size(), width(), height(), dotsPerMeterX(), and dotsPerMeterY() functions provide information about the image size @@ -365,8 +365,8 @@ bool QImageData::checkForAlphaPixels() const setOffset() function. \row - \o Colors - \o + \li Colors + \li The color of a pixel can be retrieved by passing its coordinates to the pixel() function. The pixel() function returns the color @@ -392,8 +392,8 @@ bool QImageData::checkForAlphaPixels() const sections. \row - \o Text - \o + \li Text + \li The text() function returns the image text associated with the given text key. An image's text keys can be retrieved using the @@ -401,8 +401,8 @@ bool QImageData::checkForAlphaPixels() const image's text. \row - \o Low-level information - \o + \li Low-level information + \li The depth() function returns the depth of the image. The supported depths are 1 (monochrome), 8, 16, 24 and 32 bits. The @@ -434,10 +434,10 @@ bool QImageData::checkForAlphaPixels() const \table \header - \o {2,1}32-bit + \li {2,1}32-bit \row - \o \inlineimage qimage-32bit_scaled.png - \o + \li \inlineimage qimage-32bit_scaled.png + \li \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 0 \endtable @@ -455,10 +455,10 @@ bool QImageData::checkForAlphaPixels() const \table \header - \o {2,1} 8-bit + \li {2,1} 8-bit \row - \o \inlineimage qimage-8bit_scaled.png - \o + \li \inlineimage qimage-8bit_scaled.png + \li \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 1 \endtable @@ -529,28 +529,28 @@ bool QImageData::checkForAlphaPixels() const in-place: \table - \header \o Function \o Description + \header \li Function \li Description \row - \o setDotsPerMeterX() - \o Defines the aspect ratio by setting the number of pixels that fit + \li setDotsPerMeterX() + \li Defines the aspect ratio by setting the number of pixels that fit horizontally in a physical meter. \row - \o setDotsPerMeterY() - \o Defines the aspect ratio by setting the number of pixels that fit + \li setDotsPerMeterY() + \li Defines the aspect ratio by setting the number of pixels that fit vertically in a physical meter. \row - \o fill() - \o Fills the entire image with the given pixel value. + \li fill() + \li Fills the entire image with the given pixel value. \row - \o invertPixels() - \o Inverts all pixel values in the image using the given InvertMode value. + \li invertPixels() + \li Inverts all pixel values in the image using the given InvertMode value. \row - \o setColorTable() - \o Sets the color table used to translate color indexes. Only + \li setColorTable() + \li Sets the color table used to translate color indexes. Only monochrome and 8-bit formats. \row - \o setColorCount() - \o Resizes the color table. Only monochrome and 8-bit formats. + \li setColorCount() + \li Resizes the color table. Only monochrome and 8-bit formats. \endtable @@ -3794,11 +3794,11 @@ bool QImage::isGrayscale() const \image qimage-scaling.png \list - \i If \a aspectRatioMode is Qt::IgnoreAspectRatio, the image + \li If \a aspectRatioMode is Qt::IgnoreAspectRatio, the image is scaled to \a size. - \i If \a aspectRatioMode is Qt::KeepAspectRatio, the image is + \li If \a aspectRatioMode is Qt::KeepAspectRatio, the image is scaled to a rectangle as large as possible inside \a size, preserving the aspect ratio. - \i If \a aspectRatioMode is Qt::KeepAspectRatioByExpanding, + \li If \a aspectRatioMode is Qt::KeepAspectRatioByExpanding, the image is scaled to a rectangle as small as possible outside \a size, preserving the aspect ratio. \endlist diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 4a9a9b00f4..870784f638 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -703,22 +703,22 @@ QByteArray QImageReader::format() const \list - \o Image plugins are queried first, based on either the optional format + \li Image plugins are queried first, based on either the optional format string, or the file name suffix (if the source device is a file). No content detection is done at this stage. QImageReader will choose the first plugin that supports reading for this format. - \o If no plugin supports the image format, Qt's built-in handlers are + \li If no plugin supports the image format, Qt's built-in handlers are checked based on either the optional format string, or the file name suffix. - \o If no capable plugins or built-in handlers are found, each plugin is + \li If no capable plugins or built-in handlers are found, each plugin is tested by inspecting the content of the data stream. - \o If no plugins could detect the image format based on data contents, + \li If no plugins could detect the image format based on data contents, each built-in image handler is tested by inspecting the contents. - \o Finally, if all above approaches fail, QImageReader will report failure + \li Finally, if all above approaches fail, QImageReader will report failure when trying to read the image. \endlist @@ -1423,18 +1423,18 @@ QByteArray QImageReader::imageFormat(QIODevice *device) By default, Qt can read the following formats: \table - \header \o Format \o Description - \row \o BMP \o Windows Bitmap - \row \o GIF \o Graphic Interchange Format (optional) - \row \o JPG \o Joint Photographic Experts Group - \row \o JPEG \o Joint Photographic Experts Group - \row \o PNG \o Portable Network Graphics - \row \o PBM \o Portable Bitmap - \row \o PGM \o Portable Graymap - \row \o PPM \o Portable Pixmap - \row \o XBM \o X11 Bitmap - \row \o XPM \o X11 Pixmap - \row \o SVG \o Scalable Vector Graphics + \header \li Format \li Description + \row \li BMP \li Windows Bitmap + \row \li GIF \li Graphic Interchange Format (optional) + \row \li JPG \li Joint Photographic Experts Group + \row \li JPEG \li Joint Photographic Experts Group + \row \li PNG \li Portable Network Graphics + \row \li PBM \li Portable Bitmap + \row \li PGM \li Portable Graymap + \row \li PPM \li Portable Pixmap + \row \li XBM \li X11 Bitmap + \row \li XPM \li X11 Pixmap + \row \li SVG \li Scalable Vector Graphics \endtable Reading and writing SVG files is supported through Qt's diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index 966017452c..8395f9d216 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -653,14 +653,14 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const By default, Qt can write the following formats: \table - \header \o Format \o Description - \row \o BMP \o Windows Bitmap - \row \o JPG \o Joint Photographic Experts Group - \row \o JPEG \o Joint Photographic Experts Group - \row \o PNG \o Portable Network Graphics - \row \o PPM \o Portable Pixmap - \row \o XBM \o X11 Bitmap - \row \o XPM \o X11 Pixmap + \header \li Format \li Description + \row \li BMP \li Windows Bitmap + \row \li JPG \li Joint Photographic Experts Group + \row \li JPEG \li Joint Photographic Experts Group + \row \li PNG \li Portable Network Graphics + \row \li PPM \li Portable Pixmap + \row \li XBM \li X11 Bitmap + \row \li XPM \li X11 Pixmap \endtable Reading and writing SVG files is supported through Qt's diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index e8c1304b74..504f583baf 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1052,11 +1052,11 @@ bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags fla \image qimage-scaling.png \list - \i If \a aspectRatioMode is Qt::IgnoreAspectRatio, the pixmap + \li If \a aspectRatioMode is Qt::IgnoreAspectRatio, the pixmap is scaled to \a size. - \i If \a aspectRatioMode is Qt::KeepAspectRatio, the pixmap is + \li If \a aspectRatioMode is Qt::KeepAspectRatio, the pixmap is scaled to a rectangle as large as possible inside \a size, preserving the aspect ratio. - \i If \a aspectRatioMode is Qt::KeepAspectRatioByExpanding, + \li If \a aspectRatioMode is Qt::KeepAspectRatioByExpanding, the pixmap is scaled to a rectangle as small as possible outside \a size, preserving the aspect ratio. \endlist @@ -1273,17 +1273,17 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) formats: \table - \header \o Format \o Description \o Qt's support - \row \o BMP \o Windows Bitmap \o Read/write - \row \o GIF \o Graphic Interchange Format (optional) \o Read - \row \o JPG \o Joint Photographic Experts Group \o Read/write - \row \o JPEG \o Joint Photographic Experts Group \o Read/write - \row \o PNG \o Portable Network Graphics \o Read/write - \row \o PBM \o Portable Bitmap \o Read - \row \o PGM \o Portable Graymap \o Read - \row \o PPM \o Portable Pixmap \o Read/write - \row \o XBM \o X11 Bitmap \o Read/write - \row \o XPM \o X11 Pixmap \o Read/write + \header \li Format \li Description \li Qt's support + \row \li BMP \li Windows Bitmap \li Read/write + \row \li GIF \li Graphic Interchange Format (optional) \li Read + \row \li JPG \li Joint Photographic Experts Group \li Read/write + \row \li JPEG \li Joint Photographic Experts Group \li Read/write + \row \li PNG \li Portable Network Graphics \li Read/write + \row \li PBM \li Portable Bitmap \li Read + \row \li PGM \li Portable Graymap \li Read + \row \li PPM \li Portable Pixmap \li Read/write + \row \li XBM \li X11 Bitmap \li Read/write + \row \li XPM \li X11 Pixmap \li Read/write \endtable \section1 Pixmap Information @@ -1293,17 +1293,17 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) \table \header - \o \o Available Functions + \li \li Available Functions \row - \o Geometry - \o + \li Geometry + \li The size(), width() and height() functions provide information about the pixmap's size. The rect() function returns the image's enclosing rectangle. \row - \o Alpha component - \o + \li Alpha component + \li The hasAlphaChannel() returns true if the pixmap has a format that respects the alpha channel, otherwise returns false. The hasAlpha(), @@ -1318,8 +1318,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) QBitmap) for the pixmap based on a given color. \row - \o Low-level information - \o + \li Low-level information + \li The depth() function returns the depth of the pixmap. The defaultDepth() function returns the default depth, i.e. the depth diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp index 8e881aabc7..27179cf141 100644 --- a/src/gui/kernel/qclipboard.cpp +++ b/src/gui/kernel/qclipboard.cpp @@ -86,18 +86,18 @@ QT_BEGIN_NAMESPACE \list - \i The X11 Window System has the concept of a separate selection + \li The X11 Window System has the concept of a separate selection and clipboard. When text is selected, it is immediately available as the global mouse selection. The global mouse selection may later be copied to the clipboard. By convention, the middle mouse button is used to paste the global mouse selection. - \i X11 also has the concept of ownership; if you change the + \li X11 also has the concept of ownership; if you change the selection within a window, X11 will only notify the owner and the previous owner of the change, i.e. it will not notify all applications that the selection or clipboard data changed. - \i Lastly, the X11 clipboard is event driven, i.e. the clipboard + \li Lastly, the X11 clipboard is event driven, i.e. the clipboard will not function properly if the event loop is not running. Similarly, it is recommended that the contents of the clipboard are stored or retrieved in direct response to user-input events, @@ -105,7 +105,7 @@ QT_BEGIN_NAMESPACE store or retrieve the clipboard contents in response to timer or non-user-input events. - \i Since there is no standard way to copy and paste files between + \li Since there is no standard way to copy and paste files between applications on X11, various MIME types and conventions are currently in use. For instance, Nautilus expects files to be supplied with a \c{x-special/gnome-copied-files} MIME type with data beginning with @@ -123,12 +123,12 @@ QT_BEGIN_NAMESPACE \list - \i Windows and Mac OS X do not support the global mouse + \li Windows and Mac OS X do not support the global mouse selection; they only supports the global clipboard, i.e. they only add text to the clipboard when an explicit copy or cut is made. - \i Windows and Mac OS X does not have the concept of ownership; + \li Windows and Mac OS X does not have the concept of ownership; the clipboard is a fully global resource so all applications are notified of changes. diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index 77eb1e1e9c..f16e5c85de 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -85,7 +85,7 @@ QT_BEGIN_NAMESPACE To set or get the position of the mouse cursor use the static methods QCursor::pos() and QCursor::setPos(). - \bold{Note:} It is possible to create a QCursor before + \b{Note:} It is possible to create a QCursor before QGuiApplication, but it is not useful except as a place-holder for a real QCursor created after QGuiApplication. Attempting to use a QCursor that was created before QGuiApplication will result in a @@ -104,50 +104,50 @@ QT_BEGIN_NAMESPACE theme, while others will use an internal bitmap cursor. \table - \header \o Shape \o Qt::CursorShape Value \o Cursor Name - \o Shape \o Qt::CursorShape Value \o Cursor Name - \row \o \inlineimage cursor-arrow.png - \o Qt::ArrowCursor \o \c left_ptr - \o \inlineimage cursor-sizev.png - \o Qt::SizeVerCursor \o \c size_ver - \row \o \inlineimage cursor-uparrow.png - \o Qt::UpArrowCursor \o \c up_arrow - \o \inlineimage cursor-sizeh.png - \o Qt::SizeHorCursor \o \c size_hor - \row \o \inlineimage cursor-cross.png - \o Qt::CrossCursor \o \c cross - \o \inlineimage cursor-sizeb.png - \o Qt::SizeBDiagCursor \o \c size_bdiag - \row \o \inlineimage cursor-ibeam.png - \o Qt::IBeamCursor \o \c ibeam - \o \inlineimage cursor-sizef.png - \o Qt::SizeFDiagCursor \o \c size_fdiag - \row \o \inlineimage cursor-wait.png - \o Qt::WaitCursor \o \c wait - \o \inlineimage cursor-sizeall.png - \o Qt::SizeAllCursor \o \c size_all - \row \o \inlineimage cursor-busy.png - \o Qt::BusyCursor \o \c left_ptr_watch - \o \inlineimage cursor-vsplit.png - \o Qt::SplitVCursor \o \c split_v - \row \o \inlineimage cursor-forbidden.png - \o Qt::ForbiddenCursor \o \c forbidden - \o \inlineimage cursor-hsplit.png - \o Qt::SplitHCursor \o \c split_h - \row \o \inlineimage cursor-hand.png - \o Qt::PointingHandCursor \o \c pointing_hand - \o \inlineimage cursor-openhand.png - \o Qt::OpenHandCursor \o \c openhand - \row \o \inlineimage cursor-whatsthis.png - \o Qt::WhatsThisCursor \o \c whats_this - \o \inlineimage cursor-closedhand.png - \o Qt::ClosedHandCursor \o \c closedhand - \row \o - \o Qt::DragMoveCursor \o \c dnd-move or \c move - \o - \o Qt::DragCopyCursor \o \c dnd-copy or \c copy - \row \o - \o Qt::DragLinkCursor \o \c dnd-link or \c link + \header \li Shape \li Qt::CursorShape Value \li Cursor Name + \li Shape \li Qt::CursorShape Value \li Cursor Name + \row \li \inlineimage cursor-arrow.png + \li Qt::ArrowCursor \li \c left_ptr + \li \inlineimage cursor-sizev.png + \li Qt::SizeVerCursor \li \c size_ver + \row \li \inlineimage cursor-uparrow.png + \li Qt::UpArrowCursor \li \c up_arrow + \li \inlineimage cursor-sizeh.png + \li Qt::SizeHorCursor \li \c size_hor + \row \li \inlineimage cursor-cross.png + \li Qt::CrossCursor \li \c cross + \li \inlineimage cursor-sizeb.png + \li Qt::SizeBDiagCursor \li \c size_bdiag + \row \li \inlineimage cursor-ibeam.png + \li Qt::IBeamCursor \li \c ibeam + \li \inlineimage cursor-sizef.png + \li Qt::SizeFDiagCursor \li \c size_fdiag + \row \li \inlineimage cursor-wait.png + \li Qt::WaitCursor \li \c wait + \li \inlineimage cursor-sizeall.png + \li Qt::SizeAllCursor \li \c size_all + \row \li \inlineimage cursor-busy.png + \li Qt::BusyCursor \li \c left_ptr_watch + \li \inlineimage cursor-vsplit.png + \li Qt::SplitVCursor \li \c split_v + \row \li \inlineimage cursor-forbidden.png + \li Qt::ForbiddenCursor \li \c forbidden + \li \inlineimage cursor-hsplit.png + \li Qt::SplitHCursor \li \c split_h + \row \li \inlineimage cursor-hand.png + \li Qt::PointingHandCursor \li \c pointing_hand + \li \inlineimage cursor-openhand.png + \li Qt::OpenHandCursor \li \c openhand + \row \li \inlineimage cursor-whatsthis.png + \li Qt::WhatsThisCursor \li \c whats_this + \li \inlineimage cursor-closedhand.png + \li Qt::ClosedHandCursor \li \c closedhand + \row \li + \li Qt::DragMoveCursor \li \c dnd-move or \c move + \li + \li Qt::DragCopyCursor \li \c dnd-copy or \c copy + \row \li + \li Qt::DragLinkCursor \li \c dnd-link or \c link \endtable \sa QWidget, {fowler}{GUI Design Handbook: Cursors} @@ -346,10 +346,10 @@ QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY) The cursor \a bitmap (B) and \a mask (M) bits are combined like this: \list - \o B=1 and M=1 gives black. - \o B=0 and M=1 gives white. - \o B=0 and M=0 gives transparent. - \o B=1 and M=0 gives an XOR'd result under Windows, undefined + \li B=1 and M=1 gives black. + \li B=0 and M=1 gives white. + \li B=0 and M=0 gives transparent. + \li B=1 and M=0 gives an XOR'd result under Windows, undefined results on all other platforms. \endlist diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp index ead0805bd1..40015c8706 100644 --- a/src/gui/kernel/qdrag.cpp +++ b/src/gui/kernel/qdrag.cpp @@ -176,7 +176,7 @@ QPixmap QDrag::pixmap() const Sets the position of the hot spot relative to the top-left corner of the pixmap used to the point specified by \a hotspot. - \bold{Note:} on X11, the pixmap may not be able to keep up with the mouse + \b{Note:} on X11, the pixmap may not be able to keep up with the mouse movements if the hot spot causes the pixmap to be displayed directly under the cursor. */ @@ -224,7 +224,7 @@ QObject *QDrag::target() const from are specified in \a supportedActions. The default proposed action will be selected among the allowed actions in the following order: Move, Copy and Link. - \bold{Note:} On Linux and Mac OS X, the drag and drop operation + \b{Note:} On Linux and Mac OS X, the drag and drop operation can take some time, but this function does not block the event loop. Other events are still delivered to the application while the operation is performed. On Windows, the Qt event loop is @@ -246,7 +246,7 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions) The \a defaultDropAction determines which action will be proposed when the user performs a drag without using modifier keys. - \bold{Note:} On Linux and Mac OS X, the drag and drop operation + \b{Note:} On Linux and Mac OS X, the drag and drop operation can take some time, but this function does not block the event loop. Other events are still delivered to the application while the operation is performed. On Windows, the Qt event loop is @@ -285,13 +285,13 @@ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions, Qt::DropAction defa /*! \obsolete - \bold{Note:} It is recommended to use exec() instead of this function. + \b{Note:} It is recommended to use exec() instead of this function. Starts the drag and drop operation and returns a value indicating the requested drop action when it is completed. The drop actions that the user can choose from are specified in \a request. Qt::CopyAction is always allowed. - \bold{Note:} Although the drag and drop operation can take some time, this function + \b{Note:} Although the drag and drop operation can take some time, this function does not block the event loop. Other events are still delivered to the application while the operation is performed. diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e902cbf7e2..60e754b289 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -377,9 +377,9 @@ QMouseEvent::~QMouseEvent() you will get the following QEvent::MouseMove events: \list 1 - \o A::MouseMove - \o B::MouseMove - \o C::MouseMove + \li A::MouseMove + \li B::MouseMove + \li C::MouseMove \endlist You will get the same events for QEvent::HoverMove, except that the event @@ -390,9 +390,9 @@ QMouseEvent::~QMouseEvent() In this case the events will occur in the following way: \list 1 - \o A::HoverMove - \o A::HoverMove, B::HoverMove - \o A::HoverMove, B::HoverMove, C::HoverMove + \li A::HoverMove + \li A::HoverMove, B::HoverMove + \li A::HoverMove, B::HoverMove, C::HoverMove \endlist */ @@ -1483,20 +1483,20 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos) step process: \list 1 - \o \bold{Starting to Compose} + \li \b{Starting to Compose} When the user presses the first key on a keyboard, an input context is created. This input context will contain a string of the typed characters. - \o \bold{Composing} + \li \b{Composing} With every new key pressed, the input method will try to create a matching string for the text typed so far called preedit string. While the input context is active, the user can only move the cursor inside the string belonging to this input context. - \o \bold{Completing} + \li \b{Completing} At some point, the user will activate a user interface component (perhaps using a particular key) where they can choose from a @@ -1539,10 +1539,10 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos) following steps: \list 1 - \o If the widget has selected text, the selected text should get + \li If the widget has selected text, the selected text should get removed. - \o Remove the text starting at replacementStart() with length + \li Remove the text starting at replacementStart() with length replacementLength() and replace it by the commitString(). If replacementLength() is 0, replacementStart() gives the insertion position for the commitString(). @@ -1556,7 +1556,7 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos) If the widget implements undo/redo, this operation gets added to the undo stack. - \o If there is no current preedit string, insert the + \li If there is no current preedit string, insert the preeditString() at the current cursor position; otherwise replace the previous preeditString with the one received from this event. @@ -2060,7 +2060,7 @@ QTabletEvent::~QTabletEvent() Returns the z position of the device. Typically this is represented by a wheel on a 4D Mouse. If the device does not support a Z-axis, this value is - always zero. This is \bold not the same as pressure. + always zero. This is \b not the same as pressure. \sa pressure() */ @@ -2576,11 +2576,11 @@ QHelpEvent::~QHelpEvent() \table 100% \row - \o + \li \snippet doc/src/snippets/qstatustipevent/main.cpp 1 \dots \snippet doc/src/snippets/qstatustipevent/main.cpp 3 - \o + \li \image qstatustipevent-widget.png Widget with status tip. \endtable @@ -2589,12 +2589,12 @@ QHelpEvent::~QHelpEvent() \table 100% \row - \o + \li \snippet doc/src/snippets/qstatustipevent/main.cpp 0 \snippet doc/src/snippets/qstatustipevent/main.cpp 2 \dots \snippet doc/src/snippets/qstatustipevent/main.cpp 3 - \o + \li \image qstatustipevent-action.png Action with status tip. \endtable @@ -3405,10 +3405,10 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent() \list - \i When the first touch point is detected, the destination widget is determined firstly by the + \li When the first touch point is detected, the destination widget is determined firstly by the location on screen and secondly by the propagation rules. - \i When additional touch points are detected, Qt first looks to see if there are any active + \li When additional touch points are detected, Qt first looks to see if there are any active touch points on any ancestor or descendent of the widget under the new touch point. If there are, the new touch point is grouped with the first, and the new touch point will be sent in a single QTouchEvent to the widget that handled the first touch point. (The widget under the new @@ -3430,19 +3430,19 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent() \list - \i As mentioned above, enabling touch events means multiple widgets can be receiving touch + \li As mentioned above, enabling touch events means multiple widgets can be receiving touch events simultaneously. Combined with the default QWidget::event() handling for QTouchEvents, this gives you great flexibility in designing touch user interfaces. Be aware of the implications. For example, it is possible that the user is moving a QSlider with one finger and pressing a QPushButton with another. The signals emitted by these widgets will be interleaved. - \i Recursion into the event loop using one of the exec() methods (e.g., QDialog::exec() or + \li Recursion into the event loop using one of the exec() methods (e.g., QDialog::exec() or QMenu::exec()) in a QTouchEvent event handler is not supported. Since there are multiple event recipients, recursion may cause problems, including but not limited to lost events and unexpected infinite recursion. - \i QTouchEvents are not affected by a \l{QWidget::grabMouse()}{mouse grab} or an + \li QTouchEvents are not affected by a \l{QWidget::grabMouse()}{mouse grab} or an \l{QApplication::activePopupWidget()}{active pop-up widget}. The behavior of QTouchEvents is undefined when opening a pop-up or grabbing the mouse while there are more than one active touch points. diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 09d4e98c3c..be82005a54 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -195,7 +195,7 @@ static inline void clearFontUnlocked() application's initialization and finalization. In addition, QGuiApplication handles most of the system-wide and application-wide settings. - For any GUI application using Qt, there is precisely \bold one QGuiApplication + For any GUI application using Qt, there is precisely \b one QGuiApplication object no matter whether the application has 0, 1, 2 or more windows at any given time. For non-GUI Qt applications, use QCoreApplication instead, as it does not depend on the \l QtGui library. @@ -205,30 +205,30 @@ static inline void clearFontUnlocked() QGuiApplication's main areas of responsibility are: \list - \o It initializes the application with the user's desktop settings, + \li It initializes the application with the user's desktop settings, such as palette(), font() and styleHints(). It keeps track of these properties in case the user changes the desktop globally, for example, through some kind of control panel. - \o It performs event handling, meaning that it receives events + \li It performs event handling, meaning that it receives events from the underlying window system and dispatches them to the relevant widgets. You can send your own events to windows by using sendEvent() and postEvent(). - \o It parses common command line arguments and sets its internal + \li It parses common command line arguments and sets its internal state accordingly. See the \l{QGuiApplication::QGuiApplication()} {constructor documentation} below for more details. - \o It provides localization of strings that are visible to the + \li It provides localization of strings that are visible to the user via translate(). - \o It provides some magical objects like the clipboard(). + \li It provides some magical objects like the clipboard(). - \o It knows about the application's windows. You can ask which + \li It knows about the application's windows. You can ask which window is at a certain position using topLevelAt(), get a list of topLevelWindows(), etc. - \o It manages the application's mouse cursor handling, see + \li It manages the application's mouse cursor handling, see setOverrideCursor() \endlist @@ -240,11 +240,11 @@ static inline void clearFontUnlocked() \table \header - \o{2,1} Groups of functions + \li{2,1} Groups of functions \row - \o System settings - \o desktopSettingsAware(), + \li System settings + \li desktopSettingsAware(), setDesktopSettingsAware(), styleHints(), palette(), @@ -253,8 +253,8 @@ static inline void clearFontUnlocked() setFont(). \row - \o Event handling - \o exec(), + \li Event handling + \li exec(), processEvents(), exit(), quit(). @@ -266,22 +266,22 @@ static inline void clearFontUnlocked() notify(). \row - \o Windows - \o allWindows(), + \li Windows + \li allWindows(), topLevelWindows(), focusWindow(), clipboard(), topLevelAt(). \row - \o Advanced cursor handling - \o overrideCursor(), + \li Advanced cursor handling + \li overrideCursor(), setOverrideCursor(), restoreOverrideCursor(). \row - \o Miscellaneous - \o startingUp(), + \li Miscellaneous + \li startingUp(), closingDown(), type(). \endtable @@ -309,9 +309,9 @@ static inline void clearFontUnlocked() All Qt programs automatically support the following command line options: \list - \o -reverse, sets the application's layout direction to + \li -reverse, sets the application's layout direction to Qt::RightToLeft - \o -qmljsdebugger=, activates the QML/JS debugger with a specified port. + \li -qmljsdebugger=, activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block], where block is optional and will make the application wait until a debugger connects to it. \endlist diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 7053f01196..153b2b5c2d 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -164,14 +164,14 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni three different ways: \list - \o For standard shortcuts, a \l{QKeySequence::StandardKey}{standard key} + \li For standard shortcuts, a \l{QKeySequence::StandardKey}{standard key} can be used to request the platform-specific key sequence associated with each shortcut. - \o For custom shortcuts, human-readable strings such as "Ctrl+X" can + \li For custom shortcuts, human-readable strings such as "Ctrl+X" can be used, and these can be translated into the appropriate shortcuts for users of different languages. Translations are made in the "QShortcut" context. - \o For hard-coded shortcuts, integer key codes can be specified with + \li For hard-coded shortcuts, integer key codes can be specified with a combination of values defined by the Qt::Key and Qt::Modifier enum values. Each key code consists of a single Qt::Key value and zero or more modifiers, such as Qt::SHIFT, Qt::CTRL, Qt::ALT and Qt::META. @@ -206,7 +206,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni code point of the character; for example, 'A' gives the same key sequence as Qt::Key_A. - \bold{Note:} On Mac OS X, references to "Ctrl", Qt::CTRL, Qt::Control + \b{Note:} On Mac OS X, references to "Ctrl", Qt::CTRL, Qt::Control and Qt::ControlModifier correspond to the \key Command keys on the Macintosh keyboard, and references to "Meta", Qt::META, Qt::Meta and Qt::MetaModifier correspond to the \key Control keys. Developers on @@ -225,72 +225,72 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni corresponds to the \key Control keys. \table - \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME - \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1 - \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 - \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O - \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W - \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S - \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q - \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S - \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N - \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D - \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del - \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins - \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins - \row \i Preferences \i \i Ctrl+, \i \i - \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 - \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i Ctrl+Shift+Z - \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left - \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right - \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 - \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus - \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus - \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P - \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T - \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward - \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back - \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F - \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3 - \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3 - \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H - \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A - \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B - \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I - \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U - \row \i MoveToNextChar \i Right \i Right \i Right \i Right - \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left - \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right - \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left - \row \i MoveToNextLine \i Down \i Down \i Down \i Down - \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up - \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown - \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp - \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home - \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End - \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none) - \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none) - \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home - \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End - \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right - \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left - \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right - \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left - \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down - \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up - \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown - \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp - \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home - \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End - \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up, Meta+Shift+A \i (none) \i (none) - \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down, Meta+Shift+E \i (none) \i (none) - \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home - \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End - \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace - \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del - \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K - \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter - \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter + \header \li StandardKey \li Windows \li Mac OS X \li KDE \li GNOME + \row \li HelpContents \li F1 \li Ctrl+? \li F1 \li F1 + \row \li WhatsThis \li Shift+F1 \li Shift+F1 \li Shift+F1 \li Shift+F1 + \row \li Open \li Ctrl+O \li Ctrl+O \li Ctrl+O \li Ctrl+O + \row \li Close \li Ctrl+F4, Ctrl+W \li Ctrl+W, Ctrl+F4 \li Ctrl+W \li Ctrl+W + \row \li Save \li Ctrl+S \li Ctrl+S \li Ctrl+S \li Ctrl+S + \row \li Quit \li \li Ctrl+Q \li Qtrl+Q \li Qtrl+Q + \row \li SaveAs \li \li Ctrl+Shift+S \li \li Ctrl+Shift+S + \row \li New \li Ctrl+N \li Ctrl+N \li Ctrl+N \li Ctrl+N + \row \li Delete \li Del \li Del, Meta+D \li Del, Ctrl+D \li Del, Ctrl+D + \row \li Cut \li Ctrl+X, Shift+Del \li Ctrl+X \li Ctrl+X, F20, Shift+Del \li Ctrl+X, F20, Shift+Del + \row \li Copy \li Ctrl+C, Ctrl+Ins \li Ctrl+C \li Ctrl+C, F16, Ctrl+Ins \li Ctrl+C, F16, Ctrl+Ins + \row \li Paste \li Ctrl+V, Shift+Ins \li Ctrl+V \li Ctrl+V, F18, Shift+Ins \li Ctrl+V, F18, Shift+Ins + \row \li Preferences \li \li Ctrl+, \li \li + \row \li Undo \li Ctrl+Z, Alt+Backspace \li Ctrl+Z \li Ctrl+Z, F14 \li Ctrl+Z, F14 + \row \li Redo \li Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \li Ctrl+Shift+Z \li Ctrl+Shift+Z \li Ctrl+Shift+Z + \row \li Back \li Alt+Left, Backspace \li Ctrl+[ \li Alt+Left \li Alt+Left + \row \li Forward \li Alt+Right, Shift+Backspace \li Ctrl+] \li Alt+Right \li Alt+Right + \row \li Refresh \li F5 \li F5 \li F5 \li Ctrl+R, F5 + \row \li ZoomIn \li Ctrl+Plus \li Ctrl+Plus \li Ctrl+Plus \li Ctrl+Plus + \row \li ZoomOut \li Ctrl+Minus \li Ctrl+Minus \li Ctrl+Minus \li Ctrl+Minus + \row \li Print \li Ctrl+P \li Ctrl+P \li Ctrl+P \li Ctrl+P + \row \li AddTab \li Ctrl+T \li Ctrl+T \li Ctrl+Shift+N, Ctrl+T \li Ctrl+T + \row \li NextChild \li Ctrl+Tab, Forward, Ctrl+F6 \li Ctrl+}, Forward, Ctrl+Tab \li Ctrl+Tab, Forward, Ctrl+Comma \li Ctrl+Tab, Forward + \row \li PreviousChild \li Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \li Ctrl+{, Back, Ctrl+Shift+Tab \li Ctrl+Shift+Tab, Back, Ctrl+Period \li Ctrl+Shift+Tab, Back + \row \li Find \li Ctrl+F \li Ctrl+F \li Ctrl+F \li Ctrl+F + \row \li FindNext \li F3, Ctrl+G \li Ctrl+G \li F3 \li Ctrl+G, F3 + \row \li FindPrevious \li Shift+F3, Ctrl+Shift+G \li Ctrl+Shift+G \li Shift+F3 \li Ctrl+Shift+G, Shift+F3 + \row \li Replace \li Ctrl+H \li (none) \li Ctrl+R \li Ctrl+H + \row \li SelectAll \li Ctrl+A \li Ctrl+A \li Ctrl+A \li Ctrl+A + \row \li Bold \li Ctrl+B \li Ctrl+B \li Ctrl+B \li Ctrl+B + \row \li Italic \li Ctrl+I \li Ctrl+I \li Ctrl+I \li Ctrl+I + \row \li Underline \li Ctrl+U \li Ctrl+U \li Ctrl+U \li Ctrl+U + \row \li MoveToNextChar \li Right \li Right \li Right \li Right + \row \li MoveToPreviousChar \li Left \li Left \li Left \li Left + \row \li MoveToNextWord \li Ctrl+Right \li Alt+Right \li Ctrl+Right \li Ctrl+Right + \row \li MoveToPreviousWord \li Ctrl+Left \li Alt+Left \li Ctrl+Left \li Ctrl+Left + \row \li MoveToNextLine \li Down \li Down \li Down \li Down + \row \li MoveToPreviousLine \li Up \li Up \li Up \li Up + \row \li MoveToNextPage \li PgDown \li PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\li PgDown \li PgDown + \row \li MoveToPreviousPage \li PgUp \li PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \li PgUp \li PgUp + \row \li MoveToStartOfLine \li Home \li Ctrl+Left, Meta+Left \li Home \li Home + \row \li MoveToEndOfLine \li End \li Ctrl+Right, Meta+Right \li End \li End + \row \li MoveToStartOfBlock \li (none) \li Alt+Up, Meta+A \li (none) \li (none) + \row \li MoveToEndOfBlock \li (none) \li Alt+Down, Meta+E \li (none) \li (none) + \row \li MoveToStartOfDocument\li Ctrl+Home \li Ctrl+Up, Home \li Ctrl+Home \li Ctrl+Home + \row \li MoveToEndOfDocument \li Ctrl+End \li Ctrl+Down, End \li Ctrl+End \li Ctrl+End + \row \li SelectNextChar \li Shift+Right \li Shift+Right \li Shift+Right \li Shift+Right + \row \li SelectPreviousChar \li Shift+Left \li Shift+Left \li Shift+Left \li Shift+Left + \row \li SelectNextWord \li Ctrl+Shift+Right \li Alt+Shift+Right \li Ctrl+Shift+Right \li Ctrl+Shift+Right + \row \li SelectPreviousWord \li Ctrl+Shift+Left \li Alt+Shift+Left \li Ctrl+Shift+Left \li Ctrl+Shift+Left + \row \li SelectNextLine \li Shift+Down \li Shift+Down \li Shift+Down \li Shift+Down + \row \li SelectPreviousLine \li Shift+Up \li Shift+Up \li Shift+Up \li Shift+Up + \row \li SelectNextPage \li Shift+PgDown \li Shift+PgDown \li Shift+PgDown \li Shift+PgDown + \row \li SelectPreviousPage \li Shift+PgUp \li Shift+PgUp \li Shift+PgUp \li Shift+PgUp + \row \li SelectStartOfLine \li Shift+Home \li Ctrl+Shift+Left \li Shift+Home \li Shift+Home + \row \li SelectEndOfLine \li Shift+End \li Ctrl+Shift+Right \li Shift+End \li Shift+End + \row \li SelectStartOfBlock \li (none) \li Alt+Shift+Up, Meta+Shift+A \li (none) \li (none) + \row \li SelectEndOfBlock \li (none) \li Alt+Shift+Down, Meta+Shift+E \li (none) \li (none) + \row \li SelectStartOfDocument\li Ctrl+Shift+Home \li Ctrl+Shift+Up, Shift+Home \li Ctrl+Shift+Home\li Ctrl+Shift+Home + \row \li SelectEndOfDocument \li Ctrl+Shift+End \li Ctrl+Shift+Down, Shift+End \li Ctrl+Shift+End \li Ctrl+Shift+End + \row \li DeleteStartOfWord \li Ctrl+Backspace \li Alt+Backspace \li Ctrl+Backspace \li Ctrl+Backspace + \row \li DeleteEndOfWord \li Ctrl+Del \li (none) \li Ctrl+Del \li Ctrl+Del + \row \li DeleteEndOfLine \li (none) \li (none) \li Ctrl+K \li Ctrl+K + \row \li InsertParagraphSeparator \li Enter \li Enter \li Enter \li Enter + \row \li InsertLineSeparator \li Shift+Enter \li Meta+Enter \li Shift+Enter \li Shift+Enter \endtable Note that, since the key sequences used for the standard shortcuts differ diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index 6d3d1c9580..8ee62ce8d9 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -342,9 +342,9 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button) The color groups: \list - \i The Active group is used for the window that has keyboard focus. - \i The Inactive group is used for other windows. - \i The Disabled group is used for widgets (not windows) that are + \li The Active group is used for the window that has keyboard focus. + \li The Inactive group is used for other windows. + \li The Disabled group is used for widgets (not windows) that are disabled for some reason. \endlist diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.cpp b/src/gui/kernel/qplatformnativeinterface_qpa.cpp index 7237849011..f87a2956a3 100644 --- a/src/gui/kernel/qplatformnativeinterface_qpa.cpp +++ b/src/gui/kernel/qplatformnativeinterface_qpa.cpp @@ -132,7 +132,7 @@ void QPlatformNativeInterface::setWindowProperty(QPlatformWindow *window, const The event filter function set here is called for all messages received from the platform if they are given type \eventType. - It is \i not called for messages that are not meant for Qt objects. + It is \e not called for messages that are not meant for Qt objects. The type of event is specific to the platform plugin chosen at run-time. diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp index 113b767e9f..08ed0ae40f 100644 --- a/src/gui/math3d/qgenericmatrix.cpp +++ b/src/gui/math3d/qgenericmatrix.cpp @@ -53,9 +53,9 @@ QT_BEGIN_NAMESPACE The QGenericMatrix template has three parameters: \table - \row \i N \i Number of columns. - \row \i M \i Number of rows. - \row \i T \i Element type that is visible to users of the class. + \row \li N \li Number of columns. + \row \li M \li Number of rows. + \row \li T \li Element type that is visible to users of the class. \endtable \sa QMatrix4x4 diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 068b2e36f7..0eb3506779 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -62,11 +62,11 @@ QT_BEGIN_NAMESPACE Internally the data is stored as column-major format, so as to be optimal for passing to OpenGL functions, which expect column-major data. - When using these functions be aware that they return data in \bold{column-major} + When using these functions be aware that they return data in \b{column-major} format: \list - \o data() - \o constData() + \li data() + \li constData() \endlist \sa QVector3D, QGenericMatrix diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index 897fa356d3..3c3581f3f4 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE The QVector2D class can also be used to represent vertices in 2D space. We therefore do not need to provide a separate vertex class. - \bold{Note:} By design values in the QVector2D instance are stored as \c float. + \b{Note:} By design values in the QVector2D instance are stored as \c float. This means that on platforms where the \c qreal arguments to QVector2D functions are represented by \c double values, it is possible to lose precision. diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 5251f9c015..adf3da4010 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE The QVector3D class can also be used to represent vertices in 3D space. We therefore do not need to provide a separate vertex class. - \bold{Note:} By design values in the QVector3D instance are stored as \c float. + \b{Note:} By design values in the QVector3D instance are stored as \c float. This means that on platforms where the \c qreal arguments to QVector3D functions are represented by \c double values, it is possible to lose precision. diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index e7ee46b88b..6b29221d92 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE The QVector4D class can also be used to represent vertices in 4D space. We therefore do not need to provide a separate vertex class. - \bold{Note:} By design values in the QVector4D instance are stored as \c float. + \b{Note:} By design values in the QVector4D instance are stored as \c float. This means that on platforms where the \c qreal arguments to QVector4D functions are represented by \c double values, it is possible to lose precision. diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index aa4941706a..cc5750490d 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -83,10 +83,10 @@ QT_BEGIN_NAMESPACE A framebuffer object has several characteristics: \list - \i \link setSamples() Number of samples per pixels.\endlink - \i \link setAttachment() Depth and/or stencil attachments.\endlink - \i \link setTextureTarget() Texture target.\endlink - \i \link setInternalTextureFormat() Internal texture format.\endlink + \li \link setSamples() Number of samples per pixels.\endlink + \li \link setAttachment() Depth and/or stencil attachments.\endlink + \li \link setTextureTarget() Texture target.\endlink + \li \link setInternalTextureFormat() Internal texture format.\endlink \endlist Note that the desired attachments or number of samples per pixels might not @@ -657,7 +657,7 @@ void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpen generates a 2D OpenGL texture (using the \c{GL_TEXTURE_2D} target), which is used as the internal rendering target. - \bold{It is important to have a current OpenGL context when creating a + \b{It is important to have a current OpenGL context when creating a QOpenGLFramebufferObject, otherwise initialization will fail.} When using a QPainter to paint to a QOpenGLFramebufferObject you should take diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 6850eac59e..fe9b370189 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -309,15 +309,15 @@ struct QBrushDataPointerDeleter otherwise false. A brush is considered opaque if: \list - \o The alpha component of the color() is 255. - \o Its texture() does not have an alpha channel and is not a QBitmap. - \o The colors in the gradient() all have an alpha component that is 255. + \li The alpha component of the color() is 255. + \li Its texture() does not have an alpha channel and is not a QBitmap. + \li The colors in the gradient() all have an alpha component that is 255. \endlist \table 100% \row - \o \inlineimage brush-outline.png Outlines - \o + \li \inlineimage brush-outline.png Outlines + \li To specify the style and color of lines and outlines, use the QPainter's \l {QPen}{pen} combined with Qt::PenStyle and @@ -826,10 +826,10 @@ Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush) is considered opaque if: \list - \i The alpha component of the color() is 255. - \i Its texture() does not have an alpha channel and is not a QBitmap. - \i The colors in the gradient() all have an alpha component that is 255. - \i It is an extended radial gradient. + \li The alpha component of the color() is 255. + \li Its texture() does not have an alpha channel and is not a QBitmap. + \li The colors in the gradient() all have an alpha component that is 255. + \li It is an extended radial gradient. \endlist */ @@ -1178,12 +1178,12 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) Qt currently supports three types of gradient fills: \list - \o \e Linear gradients interpolate colors between start and end points. - \o \e Simple radial gradients interpolate colors between a focal point + \li \e Linear gradients interpolate colors between start and end points. + \li \e Simple radial gradients interpolate colors between a focal point and end points on a circle surrounding it. - \o \e Extended radial gradients interpolate colors between a center and + \li \e Extended radial gradients interpolate colors between a center and a focal circle. - \o \e Conical gradients interpolate colors around a center point. + \li \e Conical gradients interpolate colors around a center point. \endlist A gradient's type can be retrieved using the type() function. @@ -1191,13 +1191,13 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) \table \header - \o QLinearGradient - \o QRadialGradient - \o QConicalGradient + \li QLinearGradient + \li QRadialGradient + \li QConicalGradient \row - \o \inlineimage qgradient-linear.png - \o \inlineimage qgradient-radial.png - \o \inlineimage qgradient-conical.png + \li \inlineimage qgradient-linear.png + \li \inlineimage qgradient-radial.png + \li \inlineimage qgradient-conical.png \endtable The colors in a gradient are defined using stop points of the @@ -1232,13 +1232,13 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) \table \row - \o \inlineimage qradialgradient-pad.png - \o \inlineimage qradialgradient-repeat.png - \o \inlineimage qradialgradient-reflect.png + \li \inlineimage qradialgradient-pad.png + \li \inlineimage qradialgradient-repeat.png + \li \inlineimage qradialgradient-reflect.png \row - \o \l {QGradient::PadSpread}{PadSpread} - \o \l {QGradient::RepeatSpread}{RepeatSpread} - \o \l {QGradient::ReflectSpread}{ReflectSpread} + \li \l {QGradient::PadSpread}{PadSpread} + \li \l {QGradient::RepeatSpread}{RepeatSpread} + \li \l {QGradient::ReflectSpread}{ReflectSpread} \endtable Note that the setSpread() function only has effect for linear and @@ -1537,13 +1537,13 @@ bool QGradient::operator==(const QGradient &gradient) const \table \row - \o \inlineimage qlineargradient-pad.png - \o \inlineimage qlineargradient-reflect.png - \o \inlineimage qlineargradient-repeat.png + \li \inlineimage qlineargradient-pad.png + \li \inlineimage qlineargradient-reflect.png + \li \inlineimage qlineargradient-repeat.png \row - \o \l {QGradient::PadSpread}{PadSpread} (default) - \o \l {QGradient::ReflectSpread}{ReflectSpread} - \o \l {QGradient::RepeatSpread}{RepeatSpread} + \li \l {QGradient::PadSpread}{PadSpread} (default) + \li \l {QGradient::ReflectSpread}{ReflectSpread} + \li \l {QGradient::RepeatSpread}{RepeatSpread} \endtable The colors in a gradient is defined using stop points of the @@ -1723,13 +1723,13 @@ void QLinearGradient::setFinalStop(const QPointF &stop) \table \row - \o \inlineimage qradialgradient-pad.png - \o \inlineimage qradialgradient-reflect.png - \o \inlineimage qradialgradient-repeat.png + \li \inlineimage qradialgradient-pad.png + \li \inlineimage qradialgradient-reflect.png + \li \inlineimage qradialgradient-repeat.png \row - \o \l {QGradient::PadSpread}{PadSpread} (default) - \o \l {QGradient::ReflectSpread}{ReflectSpread} - \o \l {QGradient::RepeatSpread}{RepeatSpread} + \li \l {QGradient::PadSpread}{PadSpread} (default) + \li \l {QGradient::ReflectSpread}{ReflectSpread} + \li \l {QGradient::RepeatSpread}{RepeatSpread} \endtable The colors in a gradient is defined using stop points of the diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 96491918cd..f531565fb9 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -69,11 +69,11 @@ QT_BEGIN_NAMESPACE \table \header - \o RGB \o HSV \o CMYK + \li RGB \li HSV \li CMYK \row - \o \inlineimage qcolor-rgb.png - \o \inlineimage qcolor-hsv.png - \o \inlineimage qcolor-cmyk.png + \li \inlineimage qcolor-rgb.png + \li \inlineimage qcolor-hsv.png + \li \inlineimage qcolor-cmyk.png \endtable The QColor constructor creates the color based on RGB values. To @@ -194,20 +194,20 @@ QT_BEGIN_NAMESPACE HSV, like RGB, has three components: \list - \o H, for hue, is in the range 0 to 359 if the color is chromatic (not + \li H, for hue, is in the range 0 to 359 if the color is chromatic (not gray), or meaningless if it is gray. It represents degrees on the color wheel familiar to most people. Red is 0 (degrees), green is 120, and blue is 240. \inlineimage qcolor-hue.png - \o S, for saturation, is in the range 0 to 255, and the bigger it is, + \li S, for saturation, is in the range 0 to 255, and the bigger it is, the stronger the color is. Grayish colors have saturation near 0; very strong colors have saturation near 255. \inlineimage qcolor-saturation.png - \o V, for value, is in the range 0 to 255 and represents lightness or + \li V, for value, is in the range 0 to 255 and represents lightness or brightness of the color. 0 is black; 255 is as far from black as possible. @@ -498,16 +498,16 @@ QString QColor::name() const of these formats: \list - \i #RGB (each of R, G, and B is a single hex digit) - \i #RRGGBB - \i #RRRGGGBBB - \i #RRRRGGGGBBBB - \i A name from the list of colors defined in the list of \l{SVG color keyword names} + \li #RGB (each of R, G, and B is a single hex digit) + \li #RRGGBB + \li #RRRGGGBBB + \li #RRRRGGGGBBBB + \li A name from the list of colors defined in the list of \l{SVG color keyword names} provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro". These color names work on all platforms. Note that these color names are \e not the same as defined by the Qt::GlobalColor enums, e.g. "green" and Qt::green does not refer to the same color. - \i \c transparent - representing the absence of a color. + \li \c transparent - representing the absence of a color. \endlist The color is invalid if \a name cannot be parsed. diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 6b5eb14f5f..ced2e4548c 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -111,8 +111,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qmatrix-simpletransformation.png - \o + \li \inlineimage qmatrix-simpletransformation.png + \li \snippet doc/src/snippets/matrix/matrix.cpp 0 \endtable @@ -123,8 +123,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qmatrix-combinedtransformation.png - \o + \li \inlineimage qmatrix-combinedtransformation.png + \li \snippet doc/src/snippets/matrix/matrix.cpp 1 \endtable @@ -171,8 +171,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qmatrix-combinedtransformation.png - \o + \li \inlineimage qmatrix-combinedtransformation.png + \li \snippet doc/src/snippets/matrix/matrix.cpp 2 \endtable diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 43429abe8a..0f5468df4e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -984,41 +984,41 @@ void QPainterPrivate::updateState(QPainterState *newState) \list - \o font() is the font used for drawing text. If the painter + \li font() is the font used for drawing text. If the painter isActive(), you can retrieve information about the currently set font, and its metrics, using the fontInfo() and fontMetrics() functions respectively. - \o brush() defines the color or pattern that is used for filling + \li brush() defines the color or pattern that is used for filling shapes. - \o pen() defines the color or stipple that is used for drawing + \li pen() defines the color or stipple that is used for drawing lines or boundaries. - \o backgroundMode() defines whether there is a background() or + \li backgroundMode() defines whether there is a background() or not, i.e it is either Qt::OpaqueMode or Qt::TransparentMode. - \o background() only applies when backgroundMode() is \l + \li background() only applies when backgroundMode() is \l Qt::OpaqueMode and pen() is a stipple. In that case, it describes the color of the background pixels in the stipple. - \o brushOrigin() defines the origin of the tiled brushes, normally + \li brushOrigin() defines the origin of the tiled brushes, normally the origin of widget's background. - \o viewport(), window(), worldTransform() make up the painter's coordinate + \li viewport(), window(), worldTransform() make up the painter's coordinate transformation system. For more information, see the \l {Coordinate Transformations} section and the \l {Coordinate System} documentation. - \o hasClipping() tells whether the painter clips at all. (The paint + \li hasClipping() tells whether the painter clips at all. (The paint device clips, too.) If the painter clips, it clips to clipRegion(). - \o layoutDirection() defines the layout direction used by the + \li layoutDirection() defines the layout direction used by the painter when drawing text. - \o worldMatrixEnabled() tells whether world transformation is enabled. + \li worldMatrixEnabled() tells whether world transformation is enabled. - \o viewTransformEnabled() tells whether view transformation is + \li viewTransformEnabled() tells whether view transformation is enabled. \endlist @@ -1052,9 +1052,9 @@ void QPainterPrivate::updateState(QPainterState *newState) \table 100% \row - \o \inlineimage qpainter-basicdrawing.png - \o - \bold {Basic Drawing Example} + \li \inlineimage qpainter-basicdrawing.png + \li + \b {Basic Drawing Example} The \l {painting/basicdrawing}{Basic Drawing} example shows how to display basic graphics primitives in a variety of styles using the @@ -1068,8 +1068,8 @@ void QPainterPrivate::updateState(QPainterState *newState) \table 100% \row - \o - \bold {Painter Paths example} + \li + \b {Painter Paths example} The QPainterPath class provides a container for painting operations, enabling graphical shapes to be constructed and @@ -1078,7 +1078,7 @@ void QPainterPrivate::updateState(QPainterState *newState) The \l {painting/painterpaths}{Painter Paths} example shows how painter paths can be used to build complex shapes for rendering. - \o \inlineimage qpainter-painterpaths.png + \li \inlineimage qpainter-painterpaths.png \endtable QPainter also provides the fillPath() function which fills the @@ -1096,13 +1096,13 @@ void QPainterPrivate::updateState(QPainterState *newState) \table \header - \o \l {painting/deform}{Vector Deformation} - \o \l {painting/gradients}{Gradients} - \o \l {painting/pathstroke}{Path Stroking} + \li \l {painting/deform}{Vector Deformation} + \li \l {painting/gradients}{Gradients} + \li \l {painting/pathstroke}{Path Stroking} \row - \o \inlineimage qpainter-vectordeformation.png - \o \inlineimage qpainter-gradients.png - \o \inlineimage qpainter-pathstroking.png + \li \inlineimage qpainter-vectordeformation.png + \li \inlineimage qpainter-gradients.png + \li \inlineimage qpainter-pathstroking.png \endtable @@ -1136,9 +1136,9 @@ void QPainterPrivate::updateState(QPainterState *newState) \table 100% \row - \o \inlineimage qpainter-concentriccircles.png - \o - \bold {Concentric Circles Example} + \li \inlineimage qpainter-concentriccircles.png + \li + \b {Concentric Circles Example} The \l {painting/concentriccircles}{Concentric Circles} example shows the improved rendering quality that can be obtained using @@ -1176,12 +1176,12 @@ void QPainterPrivate::updateState(QPainterState *newState) \table \header - \o nop \o rotate() \o scale() \o translate() + \li nop \li rotate() \li scale() \li translate() \row - \o \inlineimage qpainter-clock.png - \o \inlineimage qpainter-rotation.png - \o \inlineimage qpainter-scale.png - \o \inlineimage qpainter-translation.png + \li \inlineimage qpainter-clock.png + \li \inlineimage qpainter-rotation.png + \li \inlineimage qpainter-scale.png + \li \inlineimage qpainter-translation.png \endtable The most commonly used transformations are scaling, rotation, @@ -1200,15 +1200,15 @@ void QPainterPrivate::updateState(QPainterState *newState) \table 100% \row - \o - \bold {Affine Transformations Example} + \li + \b {Affine Transformations Example} The \l {painting/affine}{Affine Transformations} example shows Qt's ability to perform affine transformations on painting operations. The demo also allows the user to experiment with the transformation operations and see the results immediately. - \o \inlineimage qpainter-affinetransformations.png + \li \inlineimage qpainter-affinetransformations.png \endtable All the tranformation operations operate on the transformation @@ -1282,10 +1282,10 @@ void QPainterPrivate::updateState(QPainterState *newState) \table 100% \row - \o \inlineimage qpainter-compositiondemo.png + \li \inlineimage qpainter-compositiondemo.png - \o - \bold {Composition Modes Example} + \li + \b {Composition Modes Example} The \l {painting/composition}{Composition Modes} example, available in Qt's examples directory, allows you to experiment with the various @@ -1333,14 +1333,14 @@ void QPainterPrivate::updateState(QPainterState *newState) \list - \o Raster - This backend implements all rendering in pure software + \li Raster - This backend implements all rendering in pure software and is always used to render into QImages. For optimal performance only use the format types QImage::Format_ARGB32_Premultiplied, QImage::Format_RGB32 or QImage::Format_RGB16. Any other format, including QImage::Format_ARGB32, has significantly worse performance. This engine is used by default for QWidget and QPixmap. - \o OpenGL 2.0 (ES) - This backend is the primary backend for + \li OpenGL 2.0 (ES) - This backend is the primary backend for hardware accelerated graphics. It can be run on desktop machines and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0 specification. This includes most graphics chips produced in the @@ -1348,7 +1348,7 @@ void QPainterPrivate::updateState(QPainterState *newState) onto a QOpenGLWidget or by passing \c {-graphicssystem opengl} on the command line when the underlying system supports it. - \o OpenVG - This backend implements the Khronos standard for 2D + \li OpenVG - This backend implements the Khronos standard for 2D and Vector Graphics. It is primarily for embedded devices with hardware support for OpenVG. The engine can be enabled by passing \c {-graphicssystem openvg} on the command line when @@ -1360,26 +1360,26 @@ void QPainterPrivate::updateState(QPainterState *newState) \list - \o Simple transformations, meaning translation and scaling, pluss + \li Simple transformations, meaning translation and scaling, pluss 0, 90, 180, 270 degree rotations. - \o \c drawPixmap() in combination with simple transformations and + \li \c drawPixmap() in combination with simple transformations and opacity with non-smooth transformation mode (\c QPainter::SmoothPixmapTransform not enabled as a render hint). - \o Rectangle fills with solid color, two-color linear gradients + \li Rectangle fills with solid color, two-color linear gradients and simple transforms. - \o Rectangular clipping with simple transformations and intersect + \li Rectangular clipping with simple transformations and intersect clip. - \o Composition Modes \c QPainter::CompositionMode_Source and + \li Composition Modes \c QPainter::CompositionMode_Source and QPainter::CompositionMode_SourceOver - \o Rounded rectangle filling using solid color and two-color + \li Rounded rectangle filling using solid color and two-color linear gradients fills. - \o 3x3 patched pixmaps, via qDrawBorderPixmap. + \li 3x3 patched pixmaps, via qDrawBorderPixmap. \endlist @@ -1963,14 +1963,14 @@ QPaintEngine *QPainter::paintEngine() const 2 engine: \list - \i blending is disabled - \i the depth, stencil and scissor tests are disabled - \i the active texture unit is reset to 0 - \i the depth mask, depth function and the clear depth are reset to their + \li blending is disabled + \li the depth, stencil and scissor tests are disabled + \li the active texture unit is reset to 0 + \li the depth mask, depth function and the clear depth are reset to their default values - \i the stencil mask, stencil operation and stencil function are reset to + \li the stencil mask, stencil operation and stencil function are reset to their default values - \i the current color is reset to solid white + \li the current color is reset to solid white \endlist If, for example, the OpenGL polygon mode is changed by the user inside a @@ -2885,10 +2885,10 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) The following functions can transform the coordinate system without using a QMatrix: \list - \i translate() - \i scale() - \i shear() - \i rotate() + \li translate() + \li scale() + \li shear() + \li rotate() \endlist They operate on the painter's worldMatrix() and are implemented like this: @@ -3360,8 +3360,8 @@ void QPainter::fillPath(const QPainterPath &path, const QBrush &brush) \table 100% \row - \o \inlineimage qpainter-path.png - \o + \li \inlineimage qpainter-path.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 5 \endtable @@ -3405,8 +3405,8 @@ void QPainter::drawPath(const QPainterPath &path) \table 100% \row - \o \inlineimage qpainter-line.png - \o + \li \inlineimage qpainter-line.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 6 \endtable @@ -3452,8 +3452,8 @@ void QPainter::drawPath(const QPainterPath &path) \table 100% \row - \o \inlineimage qpainter-rectangle.png - \o + \li \inlineimage qpainter-rectangle.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 7 \endtable @@ -4121,8 +4121,8 @@ const QFont &QPainter::font() const \table 100% \row - \o \inlineimage qpainter-roundrect.png - \o + \li \inlineimage qpainter-roundrect.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 8 \endtable @@ -4221,8 +4221,8 @@ void QPainter::drawRoundRect(const QRectF &r, int xRnd, int yRnd) \table 100% \row - \o \inlineimage qpainter-ellipse.png - \o + \li \inlineimage qpainter-ellipse.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 9 \endtable @@ -4347,8 +4347,8 @@ void QPainter::drawEllipse(const QRect &r) \table 100% \row - \o \inlineimage qpainter-arc.png - \o + \li \inlineimage qpainter-arc.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 10 \endtable @@ -4411,8 +4411,8 @@ void QPainter::drawArc(const QRectF &r, int a, int alen) \table 100% \row - \o \inlineimage qpainter-pie.png - \o + \li \inlineimage qpainter-pie.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 11 \endtable @@ -4480,8 +4480,8 @@ void QPainter::drawPie(const QRectF &r, int a, int alen) \table 100% \row - \o \inlineimage qpainter-chord.png - \o + \li \inlineimage qpainter-chord.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 12 \endtable @@ -4696,7 +4696,7 @@ void QPainter::drawLines(const QPoint *pointPairs, int lineCount) \table 100% \row - \o + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 13 \endtable @@ -4802,8 +4802,8 @@ void QPainter::drawPolyline(const QPoint *points, int pointCount) \table 100% \row - \o \inlineimage qpainter-polygon.png - \o + \li \inlineimage qpainter-polygon.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 14 \endtable @@ -4915,8 +4915,8 @@ void QPainter::drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fi \table 100% \row - \o \inlineimage qpainter-polygon.png - \o + \li \inlineimage qpainter-polygon.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 15 \endtable @@ -5039,7 +5039,7 @@ static inline QPointF roundInDeviceCoordinates(const QPointF &p, const QTransfor \table 100% \row - \o + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 16 \endtable @@ -5952,8 +5952,8 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br \table 100% \row - \o \inlineimage qpainter-text.png - \o + \li \inlineimage qpainter-text.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 17 \endtable @@ -5962,20 +5962,20 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br OR of the following flags: \list - \o Qt::AlignLeft - \o Qt::AlignRight - \o Qt::AlignHCenter - \o Qt::AlignJustify - \o Qt::AlignTop - \o Qt::AlignBottom - \o Qt::AlignVCenter - \o Qt::AlignCenter - \o Qt::TextDontClip - \o Qt::TextSingleLine - \o Qt::TextExpandTabs - \o Qt::TextShowMnemonic - \o Qt::TextWordWrap - \o Qt::TextIncludeTrailingSpaces + \li Qt::AlignLeft + \li Qt::AlignRight + \li Qt::AlignHCenter + \li Qt::AlignJustify + \li Qt::AlignTop + \li Qt::AlignBottom + \li Qt::AlignVCenter + \li Qt::AlignCenter + \li Qt::TextDontClip + \li Qt::TextSingleLine + \li Qt::TextExpandTabs + \li Qt::TextShowMnemonic + \li Qt::TextWordWrap + \li Qt::TextIncludeTrailingSpaces \endlist \sa Qt::AlignmentFlag, Qt::TextFlag, boundingRect(), layoutDirection() @@ -6044,18 +6044,18 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF * the following flags: \list - \o Qt::AlignLeft - \o Qt::AlignRight - \o Qt::AlignHCenter - \o Qt::AlignJustify - \o Qt::AlignTop - \o Qt::AlignBottom - \o Qt::AlignVCenter - \o Qt::AlignCenter - \o Qt::TextSingleLine - \o Qt::TextExpandTabs - \o Qt::TextShowMnemonic - \o Qt::TextWordWrap + \li Qt::AlignLeft + \li Qt::AlignRight + \li Qt::AlignHCenter + \li Qt::AlignJustify + \li Qt::AlignTop + \li Qt::AlignBottom + \li Qt::AlignVCenter + \li Qt::AlignCenter + \li Qt::TextSingleLine + \li Qt::TextExpandTabs + \li Qt::TextShowMnemonic + \li Qt::TextWordWrap \endlist By default, QPainter draws text anti-aliased. @@ -6472,18 +6472,18 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) The \a flags argument is a bitwise OR of the following flags: \list - \o Qt::AlignLeft - \o Qt::AlignRight - \o Qt::AlignHCenter - \o Qt::AlignTop - \o Qt::AlignBottom - \o Qt::AlignVCenter - \o Qt::AlignCenter - \o Qt::TextSingleLine - \o Qt::TextExpandTabs - \o Qt::TextShowMnemonic - \o Qt::TextWordWrap - \o Qt::TextIncludeTrailingSpaces + \li Qt::AlignLeft + \li Qt::AlignRight + \li Qt::AlignHCenter + \li Qt::AlignTop + \li Qt::AlignBottom + \li Qt::AlignVCenter + \li Qt::AlignCenter + \li Qt::TextSingleLine + \li Qt::TextExpandTabs + \li Qt::TextShowMnemonic + \li Qt::TextWordWrap + \li Qt::TextIncludeTrailingSpaces \endlist If several of the horizontal or several of the vertical alignment flags are set, the resulting alignment is undefined. @@ -6691,7 +6691,7 @@ void QPainter::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPo \table 100% \row - \o + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 18 \endtable @@ -7675,7 +7675,7 @@ void QPainterState::init(QPainter *p) { \table 100% \row - \o + \li \snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 20 \endtable @@ -7791,21 +7791,21 @@ void QPainterState::init(QPainter *p) { \target GetFunction \table - \header \o Property Flag \o Current Property Value - \row \o QPaintEngine::DirtyBackground \o backgroundBrush() - \row \o QPaintEngine::DirtyBackgroundMode \o backgroundMode() - \row \o QPaintEngine::DirtyBrush \o brush() - \row \o QPaintEngine::DirtyBrushOrigin \o brushOrigin() - \row \o QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath - \o clipOperation() - \row \o QPaintEngine::DirtyClipPath \o clipPath() - \row \o QPaintEngine::DirtyClipRegion \o clipRegion() - \row \o QPaintEngine::DirtyCompositionMode \o compositionMode() - \row \o QPaintEngine::DirtyFont \o font() - \row \o QPaintEngine::DirtyTransform \o transform() - \row \o QPaintEngine::DirtyClipEnabled \o isClipEnabled() - \row \o QPaintEngine::DirtyPen \o pen() - \row \o QPaintEngine::DirtyHints \o renderHints() + \header \li Property Flag \li Current Property Value + \row \li QPaintEngine::DirtyBackground \li backgroundBrush() + \row \li QPaintEngine::DirtyBackgroundMode \li backgroundMode() + \row \li QPaintEngine::DirtyBrush \li brush() + \row \li QPaintEngine::DirtyBrushOrigin \li brushOrigin() + \row \li QPaintEngine::DirtyClipRegion \e or QPaintEngine::DirtyClipPath + \li clipOperation() + \row \li QPaintEngine::DirtyClipPath \li clipPath() + \row \li QPaintEngine::DirtyClipRegion \li clipRegion() + \row \li QPaintEngine::DirtyCompositionMode \li compositionMode() + \row \li QPaintEngine::DirtyFont \li font() + \row \li QPaintEngine::DirtyTransform \li transform() + \row \li QPaintEngine::DirtyClipEnabled \li isClipEnabled() + \row \li QPaintEngine::DirtyPen \li pen() + \row \li QPaintEngine::DirtyHints \li renderHints() \endtable The QPaintEngineState class also provide the painter() function diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 25dd134401..eb67709318 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -227,8 +227,8 @@ static void qt_debug_path(const QPainterPath &path) \table 100% \row - \o \inlineimage qpainterpath-construction.png - \o + \li \inlineimage qpainterpath-construction.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 0 \endtable @@ -241,11 +241,11 @@ static void qt_debug_path(const QPainterPath &path) \table \header - \o Qt::OddEvenFill - \o Qt::WindingFill + \li Qt::OddEvenFill + \li Qt::WindingFill \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png + \li \inlineimage qt-fillrule-oddeven.png + \li \inlineimage qt-fillrule-winding.png \endtable See the Qt::FillRule documentation for the definition of the @@ -316,11 +316,11 @@ static void qt_debug_path(const QPainterPath &path) \table \header - \o \l {painting/painterpaths}{Painter Paths Example} - \o \l {painting/deform}{Vector Deformation Example} + \li \l {painting/painterpaths}{Painter Paths Example} + \li \l {painting/deform}{Vector Deformation Example} \row - \o \inlineimage qpainterpath-example.png - \o \inlineimage qpainterpath-demo.png + \li \inlineimage qpainterpath-example.png + \li \inlineimage qpainterpath-demo.png \endtable \sa QPainterPathStroker, QPainter, QRegion, {Painter Paths Example} @@ -731,8 +731,8 @@ void QPainterPath::lineTo(const QPointF &p) \table 100% \row - \o \inlineimage qpainterpath-cubicto.png - \o + \li \inlineimage qpainterpath-cubicto.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 1 \endtable @@ -858,8 +858,8 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e) \table 100% \row - \o \inlineimage qpainterpath-arcto.png - \o + \li \inlineimage qpainterpath-arcto.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 2 \endtable @@ -970,8 +970,8 @@ QPointF QPainterPath::currentPosition() const \table 100% \row - \o \inlineimage qpainterpath-addrectangle.png - \o + \li \inlineimage qpainterpath-addrectangle.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 3 \endtable @@ -1017,8 +1017,8 @@ void QPainterPath::addRect(const QRectF &r) \table 100% \row - \o \inlineimage qpainterpath-addpolygon.png - \o + \li \inlineimage qpainterpath-addpolygon.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 4 \endtable @@ -1053,8 +1053,8 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) \table 100% \row - \o \inlineimage qpainterpath-addellipse.png - \o + \li \inlineimage qpainterpath-addellipse.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 5 \endtable @@ -1105,8 +1105,8 @@ void QPainterPath::addEllipse(const QRectF &boundingRect) \table 100% \row - \o \inlineimage qpainterpath-addtext.png - \o + \li \inlineimage qpainterpath-addtext.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpainterpath.cpp 6 \endtable @@ -1281,11 +1281,11 @@ Qt::FillRule QPainterPath::fillRule() const \table \header - \o Qt::OddEvenFill (default) - \o Qt::WindingFill + \li Qt::OddEvenFill (default) + \li Qt::WindingFill \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png + \li \inlineimage qt-fillrule-oddeven.png + \li \inlineimage qt-fillrule-winding.png \endtable \sa fillRule() @@ -2457,10 +2457,10 @@ void qt_path_stroke_cubic_to(qfixed c1x, qfixed c1y, functions: \list - \o setWidth() - \o setCapStyle() - \o setJoinStyle() - \o setDashPattern() + \li setWidth() + \li setCapStyle() + \li setJoinStyle() + \li setDashPattern() \endlist The setDashPattern() function accepts both a Qt::PenStyle object diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp index 8d05eb56ff..77f0edc52f 100644 --- a/src/gui/painting/qpen.cpp +++ b/src/gui/painting/qpen.cpp @@ -104,21 +104,21 @@ typedef QPenPrivate QPenData; \table \row - \o \inlineimage qpen-solid.png - \o \inlineimage qpen-dash.png - \o \inlineimage qpen-dot.png + \li \inlineimage qpen-solid.png + \li \inlineimage qpen-dash.png + \li \inlineimage qpen-dot.png \row - \o Qt::SolidLine - \o Qt::DashLine - \o Qt::DotLine + \li Qt::SolidLine + \li Qt::DashLine + \li Qt::DotLine \row - \o \inlineimage qpen-dashdot.png - \o \inlineimage qpen-dashdotdot.png - \o \inlineimage qpen-custom.png + \li \inlineimage qpen-dashdot.png + \li \inlineimage qpen-dashdotdot.png + \li \inlineimage qpen-custom.png \row - \o Qt::DashDotLine - \o Qt::DashDotDotLine - \o Qt::CustomDashLine + \li Qt::DashDotLine + \li Qt::DashDotDotLine + \li Qt::CustomDashLine \endtable Simply use the setStyle() function to convert the pen style to @@ -153,13 +153,13 @@ typedef QPenPrivate QPenData; \table \row - \o \inlineimage qpen-square.png - \o \inlineimage qpen-flat.png - \o \inlineimage qpen-roundcap.png + \li \inlineimage qpen-square.png + \li \inlineimage qpen-flat.png + \li \inlineimage qpen-roundcap.png \row - \o Qt::SquareCap - \o Qt::FlatCap - \o Qt::RoundCap + \li Qt::SquareCap + \li Qt::FlatCap + \li Qt::RoundCap \endtable The Qt::SquareCap style is a square line end that covers the end @@ -183,13 +183,13 @@ typedef QPenPrivate QPenData; \table \row - \o \inlineimage qpen-bevel.png - \o \inlineimage qpen-miter.png - \o \inlineimage qpen-roundjoin.png + \li \inlineimage qpen-bevel.png + \li \inlineimage qpen-miter.png + \li \inlineimage qpen-roundjoin.png \row - \o Qt::BevelJoin - \o Qt::MiterJoin - \o Qt::RoundJoin + \li Qt::BevelJoin + \li Qt::MiterJoin + \li Qt::RoundJoin \endtable The Qt::BevelJoin style fills the triangular notch between the two @@ -213,8 +213,8 @@ typedef QPenPrivate QPenData; \table 100% \row - \o \inlineimage qpen-demo.png - \o \bold {\l {painting/pathstroke}{The Path Stroking Example}} + \li \inlineimage qpen-demo.png + \li \b {\l {painting/pathstroke}{The Path Stroking Example}} The Path Stroking example shows Qt's built-in dash patterns and shows how custom patterns can be used to extend the range of available @@ -474,8 +474,8 @@ QVector QPen::dashPattern() const \table 100% \row - \o \inlineimage qpen-custom.png - \o + \li \inlineimage qpen-custom.png + \li \snippet doc/src/snippets/code/src_gui_painting_qpen.cpp 3 \endtable @@ -527,8 +527,8 @@ qreal QPen::dashOffset() const to specify the dash pattern. \table - \row \o \inlineimage qpen-dashpattern.png - \o For example, a pattern where each stroke is four units long, followed by a gap + \row \li \inlineimage qpen-dashpattern.png + \li For example, a pattern where each stroke is four units long, followed by a gap of two units, will begin with the stroke when drawn as a line. However, if the dash offset is set to 4.0, any line drawn will begin with the gap. diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 48b0c00014..ebca1edddc 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -894,11 +894,11 @@ QRegion QRegion::intersect(const QRect &r) const The rectangles \e must be optimally Y-X sorted and follow these restrictions: \list - \o The rectangles must not intersect. - \o All rectangles with a given top coordinate must have the same height. - \o No two rectangles may abut horizontally (they should be combined + \li The rectangles must not intersect. + \li All rectangles with a given top coordinate must have the same height. + \li No two rectangles may abut horizontally (they should be combined into a single wider rectangle in that case). - \o The rectangles must be sorted in ascending order, with Y as the major + \li The rectangles must be sorted in ascending order, with Y as the major sort key and X as the minor sort key. \endlist \omit diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 363dd26bbf..e5c41efc15 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -156,8 +156,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qtransform-simpletransformation.png - \o + \li \inlineimage qtransform-simpletransformation.png + \li \snippet doc/src/snippets/transform/main.cpp 0 \endtable @@ -168,8 +168,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qtransform-combinedtransformation.png - \o + \li \inlineimage qtransform-combinedtransformation.png + \li \snippet doc/src/snippets/transform/main.cpp 1 \endtable @@ -218,8 +218,8 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage qtransform-combinedtransformation2.png - \o + \li \inlineimage qtransform-combinedtransformation2.png + \li \snippet doc/src/snippets/transform/main.cpp 2 \endtable diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index 86de48b1dc..589c0f701f 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -100,14 +100,14 @@ QT_BEGIN_NAMESPACE custom text object into a document: \list - \o Choose an \a objectType. The \a objectType is an integer with a + \li Choose an \a objectType. The \a objectType is an integer with a value greater or equal to QTextFormat::UserObject. - \o Create a QTextCharFormat object and set the object type to the + \li Create a QTextCharFormat object and set the object type to the chosen type using the setObjectType() function. - \o Implement the QTextObjectInterface class. - \o Call QAbstractTextDocumentLayout::registerHandler() with an instance of your + \li Implement the QTextObjectInterface class. + \li Call QAbstractTextDocumentLayout::registerHandler() with an instance of your QTextObjectInterface subclass to register your object type. - \o Insert QChar::ObjectReplacementCharacter with the aforementioned + \li Insert QChar::ObjectReplacementCharacter with the aforementioned QTextCharFormat of the chosen object type into the document. As mentioned, the functions of QTextObjectInterface \l{QTextObjectInterface::}{intrinsicSize()} and @@ -269,17 +269,17 @@ QT_BEGIN_NAMESPACE implementation of this function would have to do the following: \list - \o Determine the list of changed \l{QTextBlock}(s) using the parameters + \li Determine the list of changed \l{QTextBlock}(s) using the parameters provided. - \o Each QTextBlock object's corresponding QTextLayout object needs to + \li Each QTextBlock object's corresponding QTextLayout object needs to be processed. You can access the \l{QTextBlock}'s layout using the QTextBlock::layout() function. This processing should take the document's page size into consideration. - \o If the total number of pages changed, the pageCountChanged() signal + \li If the total number of pages changed, the pageCountChanged() signal should be emitted. - \o If the total size changed, the documentSizeChanged() signal should + \li If the total size changed, the documentSizeChanged() signal should be emitted. - \o The update() signal should be emitted to schedule a repaint of areas + \li The update() signal should be emitted to schedule a repaint of areas in the layout that require repainting. \endlist diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 3515c7dc3c..c68452d55a 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -419,14 +419,14 @@ QFontEngineData::~QFontEngineData() \target fontmatching The font matching algorithm works as follows: \list 1 - \o The specified font family is searched for. - \o If not found, the styleHint() is used to select a replacement + \li The specified font family is searched for. + \li If not found, the styleHint() is used to select a replacement family. - \o Each replacement font family is searched for. - \o If none of these are found or there was no styleHint(), "helvetica" + \li Each replacement font family is searched for. + \li If none of these are found or there was no styleHint(), "helvetica" will be searched for. - \o If "helvetica" isn't found Qt will try the lastResortFamily(). - \o If the lastResortFamily() isn't found Qt will try the + \li If "helvetica" isn't found Qt will try the lastResortFamily(). + \li If the lastResortFamily() isn't found Qt will try the lastResortFont() which will always return a name of some kind. \endlist @@ -440,10 +440,10 @@ QFontEngineData::~QFontEngineData() Once a font is found, the remaining attributes are matched in order of priority: \list 1 - \o fixedPitch() - \o pointSize() (see below) - \o weight() - \o style() + \li fixedPitch() + \li pointSize() (see below) + \li weight() + \li style() \endlist If you have a font which matches on family, even if none of the @@ -861,35 +861,35 @@ int QFont::pointSize() const \table \header - \o - \o PreferDefaultHinting - \o PreferNoHinting - \o PreferVerticalHinting - \o PreferFullHinting + \li + \li PreferDefaultHinting + \li PreferNoHinting + \li PreferVerticalHinting + \li PreferFullHinting \row - \o Windows Vista (w/o Platform Update) and earlier - \o Full hinting - \o Full hinting - \o Full hinting - \o Full hinting + \li Windows Vista (w/o Platform Update) and earlier + \li Full hinting + \li Full hinting + \li Full hinting + \li Full hinting \row - \o Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt - \o Full hinting - \o Vertical hinting - \o Vertical hinting - \o Full hinting + \li Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt + \li Full hinting + \li Vertical hinting + \li Vertical hinting + \li Full hinting \row - \o FreeType - \o Operating System setting - \o No hinting - \o Vertical hinting (light) - \o Full hinting + \li FreeType + \li Operating System setting + \li No hinting + \li Vertical hinting (light) + \li Full hinting \row - \o Cocoa on Mac OS X - \o No hinting - \o No hinting - \o No hinting - \o No hinting + \li Cocoa on Mac OS X + \li No hinting + \li No hinting + \li No hinting + \li No hinting \endtable \note Please be aware that altering the hinting preference on Windows is available through @@ -2277,7 +2277,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) There are three ways to create a QFontInfo object. \list 1 - \o Calling the QFontInfo constructor with a QFont creates a font + \li Calling the QFontInfo constructor with a QFont creates a font info object for a screen-compatible font, i.e. the font cannot be a printer font. If the font is changed later, the font info object is \e not updated. @@ -2286,12 +2286,12 @@ QDataStream &operator>>(QDataStream &s, QFont &font) inaccurate. Printer fonts are not always accessible so the nearest screen font is used if a printer font is supplied.) - \o QWidget::fontInfo() returns the font info for a widget's font. + \li QWidget::fontInfo() returns the font info for a widget's font. This is equivalent to calling QFontInfo(widget->font()). If the widget's font is changed later, the font info object is \e not updated. - \o QPainter::fontInfo() returns the font info for a painter's + \li QPainter::fontInfo() returns the font info for a painter's current font. If the painter's font is changed later, the font info object is \e not updated. \endlist diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 7fa486e1ee..468d029cf2 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2244,7 +2244,7 @@ int QFontDatabase::addApplicationFont(const QString &fileName) Currently only TrueType fonts and TrueType font collections are supported. - \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is + \b{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is currently not supported. \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont() diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 283494e316..7209fbdfc3 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -76,7 +76,7 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, QFontMetrics object: \list 1 - \o Calling the QFontMetrics constructor with a QFont creates a + \li Calling the QFontMetrics constructor with a QFont creates a font metrics object for a screen-compatible font, i.e. the font cannot be a printer font. If the font is changed later, the font metrics object is \e not updated. @@ -85,12 +85,12 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, inaccurate. Printer fonts are not always accessible so the nearest screen font is used if a printer font is supplied.) - \o QWidget::fontMetrics() returns the font metrics for a widget's + \li QWidget::fontMetrics() returns the font metrics for a widget's font. This is equivalent to QFontMetrics(widget->font()). If the widget's font is changed later, the font metrics object is \e not updated. - \o QPainter::fontMetrics() returns the font metrics for a + \li QPainter::fontMetrics() returns the font metrics for a painter's current font. If the painter's font is changed later, the font metrics object is \e not updated. \endlist @@ -713,20 +713,20 @@ QRect QFontMetrics::boundingRect(QChar ch) const The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::AlignLeft aligns to the left border, except for + \li Qt::AlignLeft aligns to the left border, except for Arabic and Hebrew where it aligns to the right. - \o Qt::AlignRight aligns to the right border, except for + \li Qt::AlignRight aligns to the right border, except for Arabic and Hebrew where it aligns to the left. - \o Qt::AlignJustify produces justified text. - \o Qt::AlignHCenter aligns horizontally centered. - \o Qt::AlignTop aligns to the top border. - \o Qt::AlignBottom aligns to the bottom border. - \o Qt::AlignVCenter aligns vertically centered - \o Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) - \o Qt::TextSingleLine ignores newline characters in the text. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordWrap breaks the text to fit the rectangle. + \li Qt::AlignJustify produces justified text. + \li Qt::AlignHCenter aligns horizontally centered. + \li Qt::AlignTop aligns to the top border. + \li Qt::AlignBottom aligns to the bottom border. + \li Qt::AlignVCenter aligns vertically centered + \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) + \li Qt::TextSingleLine ignores newline characters in the text. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical @@ -780,10 +780,10 @@ QRect QFontMetrics::boundingRect(const QRect &rect, int flags, const QString &te The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::TextSingleLine ignores newline characters. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextSingleLine ignores newline characters. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordBreak breaks the text to fit the rectangle. \endlist If Qt::TextExpandTabs is set in \a flags, then: if \a tabArray is @@ -1490,20 +1490,20 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::AlignLeft aligns to the left border, except for + \li Qt::AlignLeft aligns to the left border, except for Arabic and Hebrew where it aligns to the right. - \o Qt::AlignRight aligns to the right border, except for + \li Qt::AlignRight aligns to the right border, except for Arabic and Hebrew where it aligns to the left. - \o Qt::AlignJustify produces justified text. - \o Qt::AlignHCenter aligns horizontally centered. - \o Qt::AlignTop aligns to the top border. - \o Qt::AlignBottom aligns to the bottom border. - \o Qt::AlignVCenter aligns vertically centered - \o Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) - \o Qt::TextSingleLine ignores newline characters in the text. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordWrap breaks the text to fit the rectangle. + \li Qt::AlignJustify produces justified text. + \li Qt::AlignHCenter aligns horizontally centered. + \li Qt::AlignTop aligns to the top border. + \li Qt::AlignBottom aligns to the bottom border. + \li Qt::AlignVCenter aligns vertically centered + \li Qt::AlignCenter (== \c{Qt::AlignHCenter | Qt::AlignVCenter}) + \li Qt::TextSingleLine ignores newline characters in the text. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordWrap breaks the text to fit the rectangle. \endlist Qt::Horizontal alignment defaults to Qt::AlignLeft and vertical @@ -1517,9 +1517,9 @@ QRectF QFontMetricsF::boundingRect(QChar ch) const If Qt::TextExpandTabs is set in \a flags, the following behavior is used to interpret tab characters in the text: \list - \o If \a tabArray is non-null, it specifies a 0-terminated sequence of + \li If \a tabArray is non-null, it specifies a 0-terminated sequence of pixel-positions for tabs in the text. - \o If \a tabStops is non-zero, it is used as the tab spacing (in pixels). + \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels). \endlist Note that the bounding rectangle may extend to the left of (0, 0), @@ -1559,10 +1559,10 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& The \a flags argument is the bitwise OR of the following flags: \list - \o Qt::TextSingleLine ignores newline characters. - \o Qt::TextExpandTabs expands tabs (see below) - \o Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. - \o Qt::TextWordBreak breaks the text to fit the rectangle. + \li Qt::TextSingleLine ignores newline characters. + \li Qt::TextExpandTabs expands tabs (see below) + \li Qt::TextShowMnemonic interprets "&x" as \underline{x}; i.e., underlined. + \li Qt::TextWordBreak breaks the text to fit the rectangle. \endlist These flags are defined in \l{Qt::TextFlags}. @@ -1570,9 +1570,9 @@ QRectF QFontMetricsF::boundingRect(const QRectF &rect, int flags, const QString& If Qt::TextExpandTabs is set in \a flags, the following behavior is used to interpret tab characters in the text: \list - \o If \a tabArray is non-null, it specifies a 0-terminated sequence of + \li If \a tabArray is non-null, it specifies a 0-terminated sequence of pixel-positions for tabs in the text. - \o If \a tabStops is non-zero, it is used as the tab spacing (in pixels). + \li If \a tabStops is non-zero, it is used as the tab spacing (in pixels). \endlist Newline characters are processed as line breaks. diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 79793d5845..9fbeef4685 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -86,13 +86,13 @@ QT_BEGIN_NAMESPACE QRawFont can be constructed in a number of ways: \list - \o It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The + \li It can be constructed by calling QTextLayout::glyphs() or QTextFragment::glyphs(). The returned QGlyphs objects will contain QRawFont objects which represent the actual fonts used to render each portion of the text. - \o It can be constructed by passing a QFont object to QRawFont::fromFont(). The function + \li It can be constructed by passing a QFont object to QRawFont::fromFont(). The function will return a QRawFont object representing the font that will be selected as response to the QFont query and the selected writing system. - \o It can be constructed by passing a file name or QByteArray directly to the QRawFont + \li It can be constructed by passing a file name or QByteArray directly to the QRawFont constructor, or by calling loadFromFile() or loadFromData(). In this case, the font will not be registered in QFontDatabase, and it will not be available as part of regular font selection. diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index ddf2fb080e..0dd0d99d2a 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -950,15 +950,15 @@ QTextLayout *QTextCursorPrivate::blockLayout(QTextBlock &block) const{ document with the cursor: \list - \i Lists are ordered sequences of block elements that are decorated with + \li Lists are ordered sequences of block elements that are decorated with bullet points or symbols. These are inserted in a specified format with insertList(). - \i Tables are inserted with the insertTable() function, and can be + \li Tables are inserted with the insertTable() function, and can be given an optional format. These contain an array of cells that can be traversed using the cursor. - \i Inline images are inserted with insertImage(). The image to be + \li Inline images are inserted with insertImage(). The image to be used can be specified in an image format, or by name. - \i Frames are inserted by calling insertFrame() with a specified format. + \li Frames are inserted by calling insertFrame() with a specified format. \endlist Actions can be grouped (i.e. treated as a single action for @@ -1621,7 +1621,7 @@ void QTextCursor::selectedTableCells(int *firstRow, int *numRows, int *firstColu /*! Clears the current selection by setting the anchor to the cursor position. - Note that it does \bold{not} delete the text of the selection. + Note that it does \b{not} delete the text of the selection. \sa removeSelectedText() hasSelection() */ diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 1fad064b5c..a8991d5428 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -261,14 +261,14 @@ QTextCodec *Qt::codecForHtml(const QByteArray &ba) system. The following are the undo/redo operations of a QTextDocument: \list - \o Insertion or removal of characters. A sequence of insertions or removals + \li Insertion or removal of characters. A sequence of insertions or removals within the same text block are regarded as a single undo/redo operation. - \o Insertion or removal of text blocks. Sequences of insertion or removals + \li Insertion or removal of text blocks. Sequences of insertion or removals in a single operation (e.g., by selecting and then deleting text) are regarded as a single undo/redo operation. - \o Text character format changes. - \o Text block format changes. - \o Text block group format changes. + \li Text character format changes. + \li Text block format changes. + \li Text block group format changes. \endlist \sa QTextCursor, QTextEdit, \link richtext.html Rich Text Processing\endlink , {Text Object Example} @@ -887,7 +887,7 @@ QChar QTextDocument::characterAt(int pos) const The style sheet needs to be compliant to CSS 2.1 syntax. - \bold{Note:} Changing the default style sheet does not have any effect to the existing content + \b{Note:} Changing the default style sheet does not have any effect to the existing content of the document. \sa {Supported HTML Subset} @@ -1169,7 +1169,7 @@ void QTextDocument::setPlainText(const QString &text) The HTML formatting is respected as much as possible; for example, "bold text" will produce text where the first word has a font - weight that gives it a bold appearance: "\bold{bold} text". + weight that gives it a bold appearance: "\b{bold} text". \note It is the responsibility of the caller to make sure that the text is correctly decoded when a QString containing HTML is created diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index d43a61866d..b0bbeb7a47 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -345,10 +345,10 @@ QTextCodec *QTextDocumentWriter::codec() const By default, Qt can write the following formats: \table - \header \o Format \o Description - \row \o plaintext \o Plain text - \row \o HTML \o HyperText Markup Language - \row \o ODF \o OpenDocument Format + \header \li Format \li Description + \row \li plaintext \li Plain text + \row \li HTML \li HyperText Markup Language + \row \li ODF \li OpenDocument Format \endtable \sa setFormat() diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp index 5a642e90ef..c3c71bc021 100644 --- a/src/gui/text/qtextlist.cpp +++ b/src/gui/text/qtextlist.cpp @@ -107,7 +107,7 @@ public: Returns true if the list has no items; otherwise returns false. - \bold{Note:} Empty lists are automatically deleted by the QTextDocument that owns + \b{Note:} Empty lists are automatically deleted by the QTextDocument that owns them. \sa count() diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp index 12af933fd0..65bc8fde1e 100644 --- a/src/gui/text/qtexttable.cpp +++ b/src/gui/text/qtexttable.cpp @@ -541,22 +541,22 @@ void QTextTablePrivate::update() const \table 80% \row - \o \inlineimage texttable-split.png Original Table - \o Suppose we have a 2x3 table of names and addresses. To merge both + \li \inlineimage texttable-split.png Original Table + \li Suppose we have a 2x3 table of names and addresses. To merge both columns in the first row we invoke mergeCells() with \a row = 0, \a column = 0, \a numRows = 1 and \a numColumns = 2. \snippet doc/src/snippets/textdocument-texttable/main.cpp 0 \row - \o \inlineimage texttable-merge.png - \o This gives us the following table. To split the first row of the table + \li \inlineimage texttable-merge.png + \li This gives us the following table. To split the first row of the table back into two cells, we invoke the splitCell() function with \a numRows and \a numCols = 1. \snippet doc/src/snippets/textdocument-texttable/main.cpp 1 \row - \o \inlineimage texttable-split.png Split Table - \o This results in the original table. + \li \inlineimage texttable-split.png Split Table + \li This results in the original table. \endtable \sa QTextTableFormat diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 02552f5a53..ce16785d1d 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -82,18 +82,18 @@ QT_BEGIN_NAMESPACE \list - \i For a line edit that accepts integers from 10 to 1000 inclusive, + \li For a line edit that accepts integers from 10 to 1000 inclusive, 42 and 123 are \l Acceptable, the empty string and 5 are \l Intermediate, and "asdf" and 1114 is \l Invalid. - \i For an editable combobox that accepts URLs, any well-formed URL + \li For an editable combobox that accepts URLs, any well-formed URL is \l Acceptable, "http://example.com/," is \l Intermediate (it might be a cut and paste action that accidentally took in a comma at the end), the empty string is \l Intermediate (the user might select and delete all of the text in preparation for entering a new URL) and "http:///./" is \l Invalid. - \i For a spin box that accepts lengths, "11cm" and "1in" are \l + \li For a spin box that accepts lengths, "11cm" and "1in" are \l Acceptable, "11" and the empty string are \l Intermediate, and "http://example.com" and "hour" are \l Invalid. @@ -801,13 +801,13 @@ QDoubleValidator::Notation QDoubleValidator::notation() const When QRegExpValidator determines whether a string is \l Acceptable or not, the regexp is treated as if it begins with the start of string - assertion (\bold{^}) and ends with the end of string assertion - (\bold{$}); the match is against the entire input string, or from + assertion (\b{^}) and ends with the end of string assertion + (\b{$}); the match is against the entire input string, or from the given position if a start position greater than zero is given. If a string is a prefix of an \l Acceptable string, it is considered \l Intermediate. For example, "" and "A" are \l Intermediate for the - regexp \bold{[A-Z][0-9]} (whereas "_" would be \l Invalid). + regexp \b{[A-Z][0-9]} (whereas "_" would be \l Invalid). For a brief introduction to Qt's regexp engine, see \l QRegExp. @@ -837,7 +837,7 @@ QRegExpValidator::QRegExpValidator(QObject *parent) accepts all strings that match the regular expression \a rx. The match is made against the entire string; e.g. if the regexp is - \bold{[A-Fa-f0-9]+} it will be treated as \bold{^[A-Fa-f0-9]+$}. + \b{[A-Fa-f0-9]+} it will be treated as \b{^[A-Fa-f0-9]+$}. */ QRegExpValidator::QRegExpValidator(const QRegExp& rx, QObject *parent) @@ -862,7 +862,7 @@ QRegExpValidator::~QRegExpValidator() The \a pos parameter is set to the length of the \a input parameter. - For example, if the regular expression is \bold{\\w\\d\\d} + For example, if the regular expression is \b{\\w\\d\\d} (word-character, digit, digit) then "A57" is \l Acceptable, "E5" is \l Intermediate, and "+9" is \l Invalid. diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 740e54b833..60c28274c6 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -451,12 +451,12 @@ QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const For example, a proxy factory could apply the following rules: \list - \o if the target address is in the local network (for example, + \li if the target address is in the local network (for example, if the hostname contains no dots or if it's an IP address in the organization's range), return QNetworkProxy::NoProxy - \o if the request is FTP, return an FTP proxy - \o if the request is HTTP or HTTPS, then return an HTTP proxy - \o otherwise, return a SOCKSv5 proxy server + \li if the request is FTP, return an FTP proxy + \li if the request is HTTP or HTTPS, then return an HTTP proxy + \li otherwise, return a SOCKSv5 proxy server \endlist The lifetime of the object \a factory will be managed by diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp index 037a7fdbf3..0aa843f393 100644 --- a/src/network/bearer/qnetworkconfiguration.cpp +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -424,37 +424,37 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const \table \header - \o BearerType - \o Value + \li BearerType + \li Value \row - \o BearerUnknown - \o - \o The session is based on an unknown or unspecified bearer type. The value of the + \li BearerUnknown + \li + \li The session is based on an unknown or unspecified bearer type. The value of the string returned describes the bearer type. \row - \o BearerEthernet - \o Ethernet + \li BearerEthernet + \li Ethernet \row - \o BearerWLAN - \o WLAN + \li BearerWLAN + \li WLAN \row - \o Bearer2G - \o 2G + \li Bearer2G + \li 2G \row - \o BearerCDMA2000 - \o CDMA2000 + \li BearerCDMA2000 + \li CDMA2000 \row - \o BearerWCDMA - \o WCDMA + \li BearerWCDMA + \li WCDMA \row - \o BearerHSPA - \o HSPA + \li BearerHSPA + \li HSPA \row - \o BearerBluetooth - \o Bluetooth + \li BearerBluetooth + \li Bluetooth \row - \o BearerWiMAX - \o WiMAX + \li BearerWiMAX + \li WiMAX \endtable This function returns an empty string if this is an invalid configuration, a network diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 3f8cabe26e..ccf794633d 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -455,10 +455,10 @@ QString QNetworkSession::errorString() const \table \header - \o Key \o Description + \li Key \li Description \row - \o ActiveConfiguration - \o If the session \l isOpen() this property returns the identifier of the + \li ActiveConfiguration + \li If the session \l isOpen() this property returns the identifier of the QNetworkConfiguration that is used by this session; otherwise an empty string. The main purpose of this key is to determine which Internet access point is used @@ -479,8 +479,8 @@ QString QNetworkSession::errorString() const } \endcode \row - \o UserChoiceConfiguration - \o If the session \l isOpen() and is bound to a QNetworkConfiguration of type + \li UserChoiceConfiguration + \li If the session \l isOpen() and is bound to a QNetworkConfiguration of type UserChoice, this property returns the identifier of the QNetworkConfiguration that the configuration resolved to when \l open() was called; otherwise an empty string. @@ -492,14 +492,14 @@ QString QNetworkSession::errorString() const whereas \e ActiveConfiguration always returns identifiers to \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations. \row - \o ConnectInBackground - \o Setting this property to \e true before calling \l open() implies that the connection attempt + \li ConnectInBackground + \li Setting this property to \e true before calling \l open() implies that the connection attempt is made but if no connection can be established, the user is not connsulted and asked to select a suitable connection. This property is not set by default and support for it depends on the platform. \row - \o AutoCloseSessionTimeout - \o If the session requires polling to keep its state up to date, this property holds + \li AutoCloseSessionTimeout + \li If the session requires polling to keep its state up to date, this property holds the timeout in milliseconds before the session will automatically close. If the value of this property is -1 the session will not automatically close. This property is set to -1 by default. diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index b14fbf8c30..eef2a7fa76 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -80,9 +80,9 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas QAuthenticator supports the following authentication methods: \list - \o Basic - \o NTLM version 2 - \o Digest-MD5 + \li Basic + \li NTLM version 2 + \li Digest-MD5 \endlist \section1 Options @@ -104,8 +104,8 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas \section2 Basic \table - \header \o Option \o Direction \o Description - \row \o \tt{realm} \o Incoming \o Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Description + \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() \endtable The Basic authentication mechanism supports no outgoing options. @@ -117,8 +117,8 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas \section2 Digest-MD5 \table - \header \o Option \o Direction \o Description - \row \o \tt{realm} \o Incoming \o Contains the realm of the authentication, the same as realm() + \header \li Option \li Direction \li Description + \row \li \tt{realm} \li Incoming \li Contains the realm of the authentication, the same as realm() \endtable The Digest-MD5 authentication mechanism supports no outgoing options. diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index dd46b8126b..230abb86aa 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -822,20 +822,20 @@ QString QHostAddress::toString() const \list - \o Node-local: Addresses that are only used for communicating with + \li Node-local: Addresses that are only used for communicating with services on the same interface (e.g., the loopback interface "::1"). - \o Link-local: Addresses that are local to the network interface + \li Link-local: Addresses that are local to the network interface (\e{link}). There is always one link-local address for each IPv6 interface on your host. Link-local addresses ("fe80...") are generated from the MAC address of the local network adaptor, and are not guaranteed to be unique. - \o Site-local: Addresses that are local to the site / private network + \li Site-local: Addresses that are local to the site / private network (e.g., the company intranet). Site-local addresses ("fec0...") are usually distributed by the site router, and are not guaranteed to be unique outside of the local site. - \o Global: For globally routable addresses, such as public servers on the + \li Global: For globally routable addresses, such as public servers on the Internet. \endlist @@ -1001,9 +1001,9 @@ bool QHostAddress::isInSubnet(const QPair &subnet) const This function supports arguments in the form: \list - \o 123.123.123.123/n where n is any value between 0 and 32 - \o 123.123.123.123/255.255.255.255 - \o /n where n is any value between 0 and 128 + \li 123.123.123.123/n where n is any value between 0 and 32 + \li 123.123.123.123/255.255.255.255 + \li /n where n is any value between 0 and 128 \endlist For IP version 4, this function accepts as well missing trailing diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index 0238d22eb6..0281eaf48b 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -139,35 +139,35 @@ \table \header - \o Proxy type - \o Description - \o Default capabilities + \li Proxy type + \li Description + \li Default capabilities \row - \o SOCKS 5 - \o Generic proxy for any kind of connection. Supports TCP, + \li SOCKS 5 + \li Generic proxy for any kind of connection. Supports TCP, UDP, binding to a port (incoming connections) and authentication. - \o TunnelingCapability, ListeningCapability, + \li TunnelingCapability, ListeningCapability, UdpTunnelingCapability, HostNameLookupCapability \row - \o HTTP - \o Implemented using the "CONNECT" command, supports only + \li HTTP + \li Implemented using the "CONNECT" command, supports only outgoing TCP connections; supports authentication. - \o TunnelingCapability, CachingCapability, HostNameLookupCapability + \li TunnelingCapability, CachingCapability, HostNameLookupCapability \row - \o Caching-only HTTP - \o Implemented using normal HTTP commands, it is useful only + \li Caching-only HTTP + \li Implemented using normal HTTP commands, it is useful only in the context of HTTP requests (see QNetworkAccessManager) - \o CachingCapability, HostNameLookupCapability + \li CachingCapability, HostNameLookupCapability \row - \o Caching FTP - \o Implemented using an FTP proxy, it is useful only in the + \li Caching FTP + \li Implemented using an FTP proxy, it is useful only in the context of FTP requests (see QNetworkAccessManager) - \o CachingCapability, HostNameLookupCapability + \li CachingCapability, HostNameLookupCapability \endtable @@ -856,12 +856,12 @@ template<> void QSharedDataPointer::detach() the proxy: \list - \o the type of query - \o the local port number to use - \o the destination host name - \o the destination port number - \o the protocol name, such as "http" or "ftp" - \o the URL being requested + \li the type of query + \li the local port number to use + \li the destination host name + \li the destination port number + \li the protocol name, such as "http" or "ftp" + \li the URL being requested \endlist The destination host name is the host in the connection in the @@ -895,35 +895,35 @@ template<> void QSharedDataPointer::detach() \table \header - \o Query type - \o Description + \li Query type + \li Description \row - \o TcpSocket - \o Normal sockets requesting a connection to a remote server, + \li TcpSocket + \li Normal sockets requesting a connection to a remote server, like QTcpSocket. The peer hostname and peer port match the values passed to QTcpSocket::connectToHost(). The local port is usually -1, indicating the socket has no preference in which port should be used. The URL component is not used. \row - \o UdpSocket - \o Datagram-based sockets, which can both send and + \li UdpSocket + \li Datagram-based sockets, which can both send and receive. The local port, remote host or remote port fields can all be used or be left unused, depending on the characteristics of the socket. The URL component is not used. \row - \o TcpServer - \o Passive server sockets that listen on a port and await + \li TcpServer + \li Passive server sockets that listen on a port and await incoming connections from the network. Normally, only the local port is used, but the remote address could be used in specific circumstances, for example to indicate which remote host a connection is expected from. The URL component is not used. \row - \o UrlRequest - \o A more high-level request, such as those coming from + \li UrlRequest + \li A more high-level request, such as those coming from QNetworkAccessManager. These requests will inevitably use an outgoing TCP socket, but the this query type is provided to indicate that more detailed information is present in the URL @@ -1487,10 +1487,10 @@ void QNetworkProxyFactory::setApplicationProxyFactory(QNetworkProxyFactory *fact listed here. \list - \o On MacOS X, this function will ignore the Proxy Auto Configuration + \li On MacOS X, this function will ignore the Proxy Auto Configuration settings, since it cannot execute the associated ECMAScript code. - \o On Windows platforms, this function may take several seconds to + \li On Windows platforms, this function may take several seconds to execute depending on the configuration of the user's system. \endlist */ diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp index 75ed17048c..d25917ee47 100644 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ b/src/network/kernel/qnetworkproxy_mac.cpp @@ -58,14 +58,14 @@ * proxy settings for: * * \list - * \o FTP proxy - * \o Web Proxy (HTTP) - * \o Secure Web Proxy (HTTPS) - * \o Streaming Proxy (RTSP) - * \o SOCKS Proxy - * \o Gopher Proxy - * \o URL for Automatic Proxy Configuration (PAC scripts) - * \o Bypass list (by default: *.local, 169.254/16) + * \li FTP proxy + * \li Web Proxy (HTTP) + * \li Secure Web Proxy (HTTPS) + * \li Streaming Proxy (RTSP) + * \li SOCKS Proxy + * \li Gopher Proxy + * \li URL for Automatic Proxy Configuration (PAC scripts) + * \li Bypass list (by default: *.local, 169.254/16) * \endlist * * The matching configuration can be obtained by calling SCDynamicStoreCopyProxies diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 75e99fe223..2f66671530 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -56,8 +56,8 @@ you need a socket, you have two options: \list - \i Instantiate QTcpSocket or QUdpSocket. - \i Create a native socket descriptor, instantiate + \li Instantiate QTcpSocket or QUdpSocket. + \li Create a native socket descriptor, instantiate QAbstractSocket, and call setSocketDescriptor() to wrap the native socket. \endlist @@ -129,15 +129,15 @@ can be used to implement blocking sockets: \list - \o waitForConnected() blocks until a connection has been established. + \li waitForConnected() blocks until a connection has been established. - \o waitForReadyRead() blocks until new data is available for + \li waitForReadyRead() blocks until new data is available for reading. - \o waitForBytesWritten() blocks until one payload of data has been + \li waitForBytesWritten() blocks until one payload of data has been written to the socket. - \o waitForDisconnected() blocks until the connection has closed. + \li waitForDisconnected() blocks until the connection has closed. \endlist We show an example: @@ -377,15 +377,15 @@ Possible values for the \e{TypeOfServiceOption} are: \table - \header \o Value \o Description - \row \o 224 \o Network control - \row \o 192 \o Internetwork control - \row \o 160 \o CRITIC/ECP - \row \o 128 \o Flash override - \row \o 96 \o Flash - \row \o 64 \o Immediate - \row \o 32 \o Priority - \row \o 0 \o Routine + \header \li Value \li Description + \row \li 224 \li Network control + \row \li 192 \li Internetwork control + \row \li 160 \li CRITIC/ECP + \row \li 128 \li Flash override + \row \li 96 \li Flash + \row \li 64 \li Immediate + \row \li 32 \li Priority + \row \li 0 \li Routine \endtable \sa QAbstractSocket::setSocketOption(), QAbstractSocket::socketOption() @@ -1510,7 +1510,7 @@ bool QAbstractSocket::bind(quint16 port, BindMode mode) Returns true if the socket is valid and ready for use; otherwise returns false. - \bold{Note:} The socket's state must be ConnectedState before reading and + \b{Note:} The socket's state must be ConnectedState before reading and writing can occur. \sa state() @@ -1792,7 +1792,7 @@ qintptr QAbstractSocket::socketDescriptor() const The socket is opened in the mode specified by \a openMode, and enters the socket state specified by \a socketState. - \bold{Note:} It is not possible to initialize two abstract sockets + \b{Note:} It is not possible to initialize two abstract sockets with the same native socket descriptor. \sa socketDescriptor() diff --git a/src/network/socket/qtcpsocket.cpp b/src/network/socket/qtcpsocket.cpp index 706f5721b2..dff8b5efb5 100644 --- a/src/network/socket/qtcpsocket.cpp +++ b/src/network/socket/qtcpsocket.cpp @@ -58,7 +58,7 @@ allows you to establish a TCP connection and transfer streams of data. See the QAbstractSocket documentation for details. - \bold{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode. + \b{Note:} TCP sockets cannot be opened in QIODevice::Unbuffered mode. \sa QTcpServer, QUdpSocket, QNetworkAccessManager, {Fortune Server Example}, {Fortune Client Example}, diff --git a/src/network/ssl/qsslcertificateextension.cpp b/src/network/ssl/qsslcertificateextension.cpp index eef27d7c2e..89b1a929c8 100644 --- a/src/network/ssl/qsslcertificateextension.cpp +++ b/src/network/ssl/qsslcertificateextension.cpp @@ -58,26 +58,26 @@ \table \header - \o Property - \o Description + \li Property + \li Description \row - \o name - \o The human readable name of the extension, eg. 'basicConstraints'. + \li name + \li The human readable name of the extension, eg. 'basicConstraints'. \row - \o criticality - \o This is a boolean value indicating if the extension is critical + \li criticality + \li This is a boolean value indicating if the extension is critical to correctly interpreting the certificate. \row - \o oid - \o The ASN.1 object identifier that specifies which extension this + \li oid + \li The ASN.1 object identifier that specifies which extension this is. \row - \o supported - \o If this is true the structure of the extension's value will not + \li supported + \li If this is true the structure of the extension's value will not change between Qt versions. \row - \o value - \o A QVariant with a structure dependent on the type of extension. + \li value + \li A QVariant with a structure dependent on the type of extension. \endtable Whilst this class provides access to any type of extension, only @@ -90,28 +90,28 @@ \table \header - \o Name - \o OID - \o Details + \li Name + \li OID + \li Details \row - \o basicConstraints - \o 2.5.29.19 - \o Returned as a QVariantMap. The key 'ca' contains a boolean value, + \li basicConstraints + \li 2.5.29.19 + \li Returned as a QVariantMap. The key 'ca' contains a boolean value, the optional key 'pathLenConstraint' contains an integer. \row - \o authorityInfoAccess - \o 1.3.6.1.5.5.7.1.1 - \o Returned as a QVariantMap. There is a key for each access method, + \li authorityInfoAccess + \li 1.3.6.1.5.5.7.1.1 + \li Returned as a QVariantMap. There is a key for each access method, with the value being a URI. \row - \o subjectKeyIdentifier - \o 2.5.29.14 - \o Returned as a QVariant containing a QString. The string is the key + \li subjectKeyIdentifier + \li 2.5.29.14 + \li Returned as a QVariant containing a QString. The string is the key identifier. \row - \o authorityKeyIdentifier - \o 2.5.29.35 - \o Returned as a QVariantMap. The optional key 'keyid' contains the key + \li authorityKeyIdentifier + \li 2.5.29.35 + \li Returned as a QVariantMap. The optional key 'keyid' contains the key identifier as a hex string stored in a QByteArray. The optional key 'serial' contains the authority key serial number as a qlonglong. Currently there is no support for the general names field of this diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index dc530dae88..ec49c0f56e 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -67,11 +67,11 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp The settings that QSslConfiguration currently supports are: \list - \o The SSL/TLS protocol to be used - \o The certificate to be presented to the peer during connection + \li The SSL/TLS protocol to be used + \li The certificate to be presented to the peer during connection and its associated private key - \o The ciphers allowed to be used for encrypting the connection - \o The list of Certificate Authorities certificates that are + \li The ciphers allowed to be used for encrypting the connection + \li The list of Certificate Authorities certificates that are used to validate the peer's certificate \endlist @@ -81,9 +81,9 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp The state that QSslConfiguration supports are: \list - \o The certificate the peer presented during handshake, along + \li The certificate the peer presented during handshake, along with the chain leading to a CA certificate - \o The cipher used to encrypt this session + \li The cipher used to encrypt this session \endlist The state can only be obtained once the SSL connection starts, but @@ -541,10 +541,10 @@ bool QSslConfiguration::testSslOption(QSsl::SslOption option) const The default SSL configuration consists of: \list - \o no local certificate and no private key - \o protocol SecureProtocols (meaning either TLS 1.0 or SSL 3 will be used) - \o the system's default CA certificate list - \o the cipher list equal to the list of the SSL libraries' + \li no local certificate and no private key + \li protocol SecureProtocols (meaning either TLS 1.0 or SSL 3 will be used) + \li the system's default CA certificate list + \li the cipher list equal to the list of the SSL libraries' supported SSL ciphers \endlist diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 311ac5fe86..6338cbbe6f 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -132,12 +132,12 @@ The following features can also be customized: \list - \o The socket's cryptographic cipher suite can be customized before + \li The socket's cryptographic cipher suite can be customized before the handshake phase with setCiphers() and setDefaultCiphers(). - \o The socket's local certificate and private key can be customized + \li The socket's local certificate and private key can be customized before the handshake phase with setLocalCertificate() and setPrivateKey(). - \o The CA certificate database can be extended and customized with + \li The CA certificate database can be extended and customized with addCaCertificate(), addCaCertificates(), setCaCertificates(), addDefaultCaCertificate(), addDefaultCaCertificates(), and setDefaultCaCertificates(). @@ -398,7 +398,7 @@ void QSslSocket::resume() \snippet doc/src/snippets/code/src_network_ssl_qsslsocket.cpp 3 - \bold{Note:} The example above shows that text can be written to + \b{Note:} The example above shows that text can be written to the socket immediately after requesting the encrypted connection, before the encrypted() signal has been emitted. In such cases, the text is queued in the object and written to the socket \e after @@ -468,7 +468,7 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, The socket is opened in the mode specified by \a openMode, and enters the socket state specified by \a state. - \bold{Note:} It is not possible to initialize two sockets with the same + \b{Note:} It is not possible to initialize two sockets with the same native socket descriptor. \sa socketDescriptor() diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 31d6064e90..eb27e865b5 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -169,17 +169,17 @@ QGLSignalProxy *QGLSignalProxy::instance() A display format has several characteristics: \list - \i \link setDoubleBuffer() Double or single buffering.\endlink - \i \link setDepth() Depth buffer.\endlink - \i \link setRgba() RGBA or color index mode.\endlink - \i \link setAlpha() Alpha channel.\endlink - \i \link setAccum() Accumulation buffer.\endlink - \i \link setStencil() Stencil buffer.\endlink - \i \link setStereo() Stereo buffers.\endlink - \i \link setDirectRendering() Direct rendering.\endlink - \i \link setOverlay() Presence of an overlay.\endlink - \i \link setPlane() Plane of an overlay.\endlink - \i \link setSampleBuffers() Multisample buffers.\endlink + \li \link setDoubleBuffer() Double or single buffering.\endlink + \li \link setDepth() Depth buffer.\endlink + \li \link setRgba() RGBA or color index mode.\endlink + \li \link setAlpha() Alpha channel.\endlink + \li \link setAccum() Accumulation buffer.\endlink + \li \link setStencil() Stencil buffer.\endlink + \li \link setStereo() Stereo buffers.\endlink + \li \link setDirectRendering() Direct rendering.\endlink + \li \link setOverlay() Presence of an overlay.\endlink + \li \link setPlane() Plane of an overlay.\endlink + \li \link setSampleBuffers() Multisample buffers.\endlink \endlist You can also specify preferred bit depths for the color buffer, @@ -275,17 +275,17 @@ static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz, /*! Constructs a QGLFormat object with the following default settings: \list - \i \link setDoubleBuffer() Double buffer:\endlink Enabled. - \i \link setDepth() Depth buffer:\endlink Enabled. - \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled). - \i \link setAlpha() Alpha channel:\endlink Disabled. - \i \link setAccum() Accumulator buffer:\endlink Disabled. - \i \link setStencil() Stencil buffer:\endlink Enabled. - \i \link setStereo() Stereo:\endlink Disabled. - \i \link setDirectRendering() Direct rendering:\endlink Enabled. - \i \link setOverlay() Overlay:\endlink Disabled. - \i \link setPlane() Plane:\endlink 0 (i.e., normal plane). - \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \li \link setDoubleBuffer() Double buffer:\endlink Enabled. + \li \link setDepth() Depth buffer:\endlink Enabled. + \li \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled). + \li \link setAlpha() Alpha channel:\endlink Disabled. + \li \link setAccum() Accumulator buffer:\endlink Disabled. + \li \link setStencil() Stencil buffer:\endlink Enabled. + \li \link setStereo() Stereo:\endlink Disabled. + \li \link setDirectRendering() Direct rendering:\endlink Enabled. + \li \link setOverlay() Overlay:\endlink Disabled. + \li \link setPlane() Plane:\endlink 0 (i.e., normal plane). + \li \link setSampleBuffers() Multisample buffers:\endlink Disabled. \endlist */ @@ -1339,17 +1339,17 @@ void QGLFormat::setDefaultFormat(const QGLFormat &f) The default overlay format is: \list - \i \link setDoubleBuffer() Double buffer:\endlink Disabled. - \i \link setDepth() Depth buffer:\endlink Disabled. - \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled). - \i \link setAlpha() Alpha channel:\endlink Disabled. - \i \link setAccum() Accumulator buffer:\endlink Disabled. - \i \link setStencil() Stencil buffer:\endlink Disabled. - \i \link setStereo() Stereo:\endlink Disabled. - \i \link setDirectRendering() Direct rendering:\endlink Enabled. - \i \link setOverlay() Overlay:\endlink Disabled. - \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. - \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane). + \li \link setDoubleBuffer() Double buffer:\endlink Disabled. + \li \link setDepth() Depth buffer:\endlink Disabled. + \li \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled). + \li \link setAlpha() Alpha channel:\endlink Disabled. + \li \link setAccum() Accumulator buffer:\endlink Disabled. + \li \link setStencil() Stencil buffer:\endlink Disabled. + \li \link setStereo() Stereo:\endlink Disabled. + \li \link setDirectRendering() Direct rendering:\endlink Enabled. + \li \link setOverlay() Overlay:\endlink Disabled. + \li \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \li \link setPlane() Plane:\endlink 1 (i.e., first overlay plane). \endlist \sa setDefaultFormat() @@ -2642,10 +2642,10 @@ static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint tex This function supports the following use cases: \list - \i On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId, + \li On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId, to the given target rectangle, \a target, in OpenGL model space. The \a textureTarget should be a 2D texture target. - \i On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a + \li On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a beginNativePainting / endNativePainting block, and uses the engine with type QPaintEngine::OpenGL2, the function will draw the given texture, \a textureId, to the given target rectangle, \a target, @@ -2709,10 +2709,10 @@ void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum text This function supports the following use cases: \list - \i By default it draws the given texture, \a textureId, + \li By default it draws the given texture, \a textureId, at the given \a point in OpenGL model space. The \a textureTarget should be a 2D texture target. - \i If a painter is active, not inside a + \li If a painter is active, not inside a beginNativePainting / endNativePainting block, and uses the engine with type QPaintEngine::OpenGL2, the function will draw the given texture, \a textureId, at the given \a point, @@ -3104,7 +3104,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) /*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc) - \bold{Win32 only:} This virtual function chooses a pixel format + \b{Win32 only:} This virtual function chooses a pixel format that matches the OpenGL \link setFormat() format\endlink. Reimplement this function in a subclass if you need a custom context. @@ -3118,7 +3118,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) /*! \fn void *QGLContext::chooseVisual() - \bold{X11 only:} This virtual function tries to find a visual that + \b{X11 only:} This virtual function tries to find a visual that matches the format, reducing the demands if the original request cannot be met. @@ -3132,7 +3132,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) /*! \fn void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth) \internal - \bold{X11 only:} This virtual function chooses a visual that matches + \b{X11 only:} This virtual function chooses a visual that matches the OpenGL \link format() format\endlink. Reimplement this function in a subclass if you need a custom visual. @@ -3220,13 +3220,13 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) reimplement in your subclass to perform the typical OpenGL tasks: \list - \i paintGL() - Renders the OpenGL scene. Gets called whenever the widget + \li paintGL() - Renders the OpenGL scene. Gets called whenever the widget needs to be updated. - \i resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets + \li resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets called whenever the widget has been resized (and also when it is shown for the first time because all newly created widgets get a resize event automatically). - \i initializeGL() - Sets up the OpenGL rendering context, defines display + \li initializeGL() - Sets up the OpenGL rendering context, defines display lists, etc. Gets called once before the first time resizeGL() or paintGL() is called. \endlist @@ -3277,9 +3277,9 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) implement some or all of these virtual methods: \list - \i paintOverlayGL() - \i resizeOverlayGL() - \i initializeOverlayGL() + \li paintOverlayGL() + \li resizeOverlayGL() + \li initializeOverlayGL() \endlist These methods work in the same way as the normal paintGL() etc. @@ -3298,9 +3298,9 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) following way: \list - \o Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to + \li Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to set up the OpenGL state and provide a perspective transformation. - \o Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only + \li Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only OpenGL functions to draw on the widget. \endlist @@ -3308,10 +3308,10 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) to reimplement QGLWidget::paintEvent() and do the following: \list - \o Construct a QPainter object. - \o Initialize it for use on the widget with the QPainter::begin() function. - \o Draw primitives using QPainter's member functions. - \o Call QPainter::end() to finish painting. + \li Construct a QPainter object. + \li Initialize it for use on the widget with the QPainter::begin() function. + \li Draw primitives using QPainter's member functions. + \li Call QPainter::end() to finish painting. \endlist Overpainting 2D content on top of 3D content takes a little more effort. @@ -3323,7 +3323,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) As of Qt version 4.8, support for doing threaded GL rendering has been improved. There are three scenarios that we currently support: \list - \o 1. Buffer swapping in a thread. + \li 1. Buffer swapping in a thread. Swapping buffers in a double buffered context may be a synchronous, locking call that may be a costly operation in some @@ -3350,7 +3350,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) having the main thread wait while the GPU finishes the swap operation. Note that this is highly implementation dependent. - \o 2. Texture uploading in a thread. + \li 2. Texture uploading in a thread. Doing texture uploads in a thread may be very useful for applications handling large amounts of images that needs to be @@ -3363,7 +3363,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) thread. For each texture that is bound via bindTexture(), notify the main thread so that it can start using the texture. - \o 3. Using QPainter to draw into a QGLWidget in a thread. + \li 3. Using QPainter to draw into a QGLWidget in a thread. In Qt 4.8, it is possible to draw into a QGLWidget using a QPainter in a separate thread. Note that this is also possible for diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index 21b3abfdd8..ed362503ce 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -87,10 +87,10 @@ extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool); A framebuffer object has several characteristics: \list - \i \link setSamples() Number of samples per pixels.\endlink - \i \link setAttachment() Depth and/or stencil attachments.\endlink - \i \link setTextureTarget() Texture target.\endlink - \i \link setInternalTextureFormat() Internal texture format.\endlink + \li \link setSamples() Number of samples per pixels.\endlink + \li \link setAttachment() Depth and/or stencil attachments.\endlink + \li \link setTextureTarget() Texture target.\endlink + \li \link setInternalTextureFormat() Internal texture format.\endlink \endlist Note that the desired attachments or number of samples per pixels might not @@ -674,7 +674,7 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, generates a 2D GL texture (using the \c{GL_TEXTURE_2D} target), which is used as the internal rendering target. - \bold{It is important to have a current GL context when creating a + \b{It is important to have a current GL context when creating a QGLFramebufferObject, otherwise initialization will fail.} OpenGL framebuffer objects and pbuffers (see @@ -683,22 +683,22 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz, using framebuffer objects instead of pbuffers: \list 1 - \o A framebuffer object does not require a separate rendering + \li A framebuffer object does not require a separate rendering context, so no context switching will occur when switching rendering targets. There is an overhead involved in switching targets, but in general it is cheaper than a context switch to a pbuffer. - \o Rendering to dynamic textures (i.e. render-to-texture + \li Rendering to dynamic textures (i.e. render-to-texture functionality) works on all platforms. No need to do explicit copy calls from a render buffer into a texture, as was necessary on systems that did not support the \c{render_texture} extension. - \o It is possible to attach several rendering buffers (or texture + \li It is possible to attach several rendering buffers (or texture objects) to the same framebuffer object, and render to all of them without doing a context switch. - \o The OpenGL framebuffer extension is a pure GL extension with no + \li The OpenGL framebuffer extension is a pure GL extension with no system dependant WGL, CGL, or GLX parts. This makes using framebuffer objects more portable. \endlist diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index ab5a738ba7..bccac7e9a0 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -53,16 +53,16 @@ There are three approaches to using this class: \list 1 - \o \bold{We can draw into the pbuffer and convert it to a QImage + \li \b{We can draw into the pbuffer and convert it to a QImage using toImage().} This is normally much faster than calling QGLWidget::renderPixmap(). - \o \bold{We can draw into the pbuffer and copy the contents into + \li \b{We can draw into the pbuffer and copy the contents into an OpenGL texture using updateDynamicTexture().} This allows us to create dynamic textures and works on all systems with pbuffer support. - \o \bold{On systems that support it, we can bind the pbuffer to + \li \b{On systems that support it, we can bind the pbuffer to an OpenGL texture.} The texture is then updated automatically when the pbuffer contents change, eliminating the need for additional copy operations. This is supported only on Windows diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index f16eff5449..6d7c89e086 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -59,15 +59,15 @@ QT_BEGIN_NAMESPACE of QGuiApplication: \list - \o \c fontengine=native Indicates that the freetype font + \li \c fontengine=native Indicates that the freetype font engine should not be used. - \o \c gl=gdi Indicates that ARB Open GL functionality should not be used + \li \c gl=gdi Indicates that ARB Open GL functionality should not be used \endlist \section1 Tips \list - \o The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls + \li The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls the debug level. It takes the form \c{:,:}, where keyword is one of \c integration, \c windows, \c backingstore and diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 25b9336361..1239f3d8e2 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -366,10 +366,10 @@ void eatMouseMove() There 2 types of native dialogs: \list - \o Dialogs provided by the Comdlg32 library (ChooseColor, + \li Dialogs provided by the Comdlg32 library (ChooseColor, ChooseFont). They only provide a modal, blocking function call (with idle processing). - \o File dialogs are classes derived from IFileDialog. They + \li File dialogs are classes derived from IFileDialog. They inherit IModalWindow and their exec() method (calling IModalWindow::Show()) is similarly blocking, but methods like close() can be called on them from event handlers. diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 5085dfefb7..ae5053210e 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -108,11 +108,11 @@ template \section1 Testing \list - \o Install the East Asian language support and choose Japanese (say). - \o Compile the \a mainwindows/mdi example and open a text window. - \o In the language bar, switch to Japanese and choose the + \li Install the East Asian language support and choose Japanese (say). + \li Compile the \a mainwindows/mdi example and open a text window. + \li In the language bar, switch to Japanese and choose the Input method 'Hiragana'. - \o In a text editor control, type the syllable \a 'la'. + \li In a text editor control, type the syllable \a 'la'. Underlined characters show up, indicating that there is completion available. Press the Space key two times. A completion popup occurs which shows the options. diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 3e98be4741..b43362c045 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -74,9 +74,9 @@ QT_BEGIN_NAMESPACE Currently implemented keys \list - \o handle (HWND) - \o getDC (DC) - \o releaseDC Releases the previously acquired DC and returns 0. + \li handle (HWND) + \li getDC (DC) + \li releaseDC Releases the previously acquired DC and returns 0. \endlist \ingroup qt-lighthouse-win diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 570e4b3b6b..e41db3f60f 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -413,14 +413,14 @@ static bool canGetData(int cf, IDataObject * pDataObj) Qt has predefined support for the following Windows Clipboard formats: \table - \header \o Windows Format \o Equivalent MIME type - \row \o \c CF_UNICODETEXT \o \c text/plain - \row \o \c CF_TEXT \o \c text/plain - \row \o \c CF_DIB \o \c{image/xyz}, where \c xyz is + \header \li Windows Format \li Equivalent MIME type + \row \li \c CF_UNICODETEXT \li \c text/plain + \row \li \c CF_TEXT \li \c text/plain + \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is a \l{QImageWriter::supportedImageFormats()}{Qt image format} - \row \o \c CF_HDROP \o \c text/uri-list - \row \o \c CF_INETURL \o \c text/uri-list - \row \o \c CF_HTML \o \c text/html + \row \li \c CF_HDROP \li \c text/uri-list + \row \li \c CF_INETURL \li \c text/uri-list + \row \li \c CF_HTML \li \c text/html \endtable An example use of this class would be to map the Windows Metafile diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index 3ae9fe1048..6f34967ee8 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -63,11 +63,11 @@ QT_BEGIN_NAMESPACE The following methods are NOT supported for data transfer using the clipboard or drag-drop: \list - \o IDataObject::SetData -- return E_NOTIMPL - \o IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED - \o ::DUnadvise - \o ::EnumDAdvise - \o IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL + \li IDataObject::SetData -- return E_NOTIMPL + \li IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED + \li ::DUnadvise + \li ::EnumDAdvise + \li IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL (NOTE: must set pformatetcOut->ptd = NULL) \endlist diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 3e0bec8d46..b2ebe06a58 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -205,18 +205,18 @@ static bool shouldShowMaximizeButton(Qt::WindowFlags flags) Window creation is split in 3 steps: \list - \o fromWindow() Gather all required information - \o create() Create the system handle. - \o initialize() Post creation initialization steps. + \li fromWindow() Gather all required information + \li create() Create the system handle. + \li initialize() Post creation initialization steps. \endlist The reason for this split is to also enable changing the QWindowFlags by calling: \list - \o fromWindow() Gather information and determine new system styles - \o applyWindowFlags() to apply the new window system styles. - \o initialize() Post creation initialization steps. + \li fromWindow() Gather information and determine new system styles + \li applyWindowFlags() to apply the new window system styles. + \li initialize() Post creation initialization steps. \endlist Contains the window creation code formerly in qwidget_win.cpp. @@ -594,13 +594,13 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, \brief Raster or OpenGL Window. \list - \o Raster type: handleWmPaint() is implemented to + \li Raster type: handleWmPaint() is implemented to to bitblt the image. The DC can be accessed via getDC/Relase DC, which has a special handling when within a paint event (in that case, the DC obtained from BeginPaint() is returned). - \o Open GL: The first time QWindowsGLContext accesses + \li Open GL: The first time QWindowsGLContext accesses the handle, it sets up the pixelformat on the DC which in turn sets it on the window (see flag PixelFormatInitialized). diff --git a/src/printsupport/dialogs/qabstractprintdialog.cpp b/src/printsupport/dialogs/qabstractprintdialog.cpp index 1c66c1888f..4e3586f646 100644 --- a/src/printsupport/dialogs/qabstractprintdialog.cpp +++ b/src/printsupport/dialogs/qabstractprintdialog.cpp @@ -386,8 +386,8 @@ void QAbstractPrintDialogPrivate::setPrinter(QPrinter *newPrinter) \table \row - \o \inlineimage plastique-printdialog.png - \o \inlineimage plastique-printdialog-properties.png + \li \inlineimage plastique-printdialog.png + \li \inlineimage plastique-printdialog-properties.png \endtable The printer dialog (shown above in Plastique style) enables access to common diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp index d50424609a..c7b450786d 100644 --- a/src/printsupport/dialogs/qprintpreviewdialog.cpp +++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp @@ -647,13 +647,13 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged() straightforward: \list 1 - \o Create the QPrintPreviewDialog. + \li Create the QPrintPreviewDialog. You can construct a QPrintPreviewDialog with an existing QPrinter object, or you can have QPrintPreviewDialog create one for you, which will be the system default printer. - \o Connect the paintRequested() signal to a slot. + \li Connect the paintRequested() signal to a slot. When the dialog needs to generate a set of preview pages, the paintRequested() signal will be emitted. You can use the exact @@ -663,7 +663,7 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged() signal, where you draw onto the QPrinter object that is passed into the slot. - \o Call exec(). + \li Call exec(). Call QPrintPreviewDialog::exec() to show the preview dialog. \endlist diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index e0373d99e8..447c535420 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -264,14 +264,14 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke The most important parameters are: \list - \i setOrientation() tells QPrinter which page orientation to use. - \i setPaperSize() tells QPrinter what paper size to expect from the + \li setOrientation() tells QPrinter which page orientation to use. + \li setPaperSize() tells QPrinter what paper size to expect from the printer. - \i setResolution() tells QPrinter what resolution you wish the + \li setResolution() tells QPrinter what resolution you wish the printer to provide, in dots per inch (DPI). - \i setFullPage() tells QPrinter whether you want to deal with the + \li setFullPage() tells QPrinter whether you want to deal with the full page or just with the part the printer can draw on. - \i setCopyCount() tells QPrinter how many copies of the document + \li setCopyCount() tells QPrinter how many copies of the document it should print. \endlist diff --git a/src/printsupport/widgets/qprintpreviewwidget.cpp b/src/printsupport/widgets/qprintpreviewwidget.cpp index ce2c6955a0..16aea238b1 100644 --- a/src/printsupport/widgets/qprintpreviewwidget.cpp +++ b/src/printsupport/widgets/qprintpreviewwidget.cpp @@ -467,13 +467,13 @@ void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor) Using QPrintPreviewWidget is straightforward: \list 1 - \o Create the QPrintPreviewWidget + \li Create the QPrintPreviewWidget Construct the QPrintPreviewWidget either by passing in an existing QPrinter object, or have QPrintPreviewWidget create a default constructed QPrinter object for you. - \o Connect the paintRequested() signal to a slot. + \li Connect the paintRequested() signal to a slot. When the widget needs to generate a set of preview pages, a paintRequested() signal will be emitted from the widget. Connect a diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 7b6a2b8c12..d4633cea57 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -650,16 +650,16 @@ QStringList QSqlDatabase::connectionNames() The currently available driver types are: \table - \header \i Driver Type \i Description - \row \i QDB2 \i IBM DB2 - \row \i QIBASE \i Borland InterBase Driver - \row \i QMYSQL \i MySQL Driver - \row \i QOCI \i Oracle Call Interface Driver - \row \i QODBC \i ODBC Driver (includes Microsoft SQL Server) - \row \i QPSQL \i PostgreSQL Driver - \row \i QSQLITE \i SQLite version 3 or above - \row \i QSQLITE2 \i SQLite version 2 - \row \i QTDS \i Sybase Adaptive Server + \header \li Driver Type \li Description + \row \li QDB2 \li IBM DB2 + \row \li QIBASE \li Borland InterBase Driver + \row \li QMYSQL \li MySQL Driver + \row \li QOCI \li Oracle Call Interface Driver + \row \li QODBC \li ODBC Driver (includes Microsoft SQL Server) + \row \li QPSQL \li PostgreSQL Driver + \row \li QSQLITE \li SQLite version 3 or above + \row \li QSQLITE2 \li SQLite version 2 + \row \li QTDS \li Sybase Adaptive Server \endtable Additional third party drivers, including your own custom @@ -1202,77 +1202,77 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const database client used: \table - \header \i ODBC \i MySQL \i PostgreSQL + \header \li ODBC \li MySQL \li PostgreSQL \row - \i + \li \list - \i SQL_ATTR_ACCESS_MODE - \i SQL_ATTR_LOGIN_TIMEOUT - \i SQL_ATTR_CONNECTION_TIMEOUT - \i SQL_ATTR_CURRENT_CATALOG - \i SQL_ATTR_METADATA_ID - \i SQL_ATTR_PACKET_SIZE - \i SQL_ATTR_TRACEFILE - \i SQL_ATTR_TRACE - \i SQL_ATTR_CONNECTION_POOLING - \i SQL_ATTR_ODBC_VERSION + \li SQL_ATTR_ACCESS_MODE + \li SQL_ATTR_LOGIN_TIMEOUT + \li SQL_ATTR_CONNECTION_TIMEOUT + \li SQL_ATTR_CURRENT_CATALOG + \li SQL_ATTR_METADATA_ID + \li SQL_ATTR_PACKET_SIZE + \li SQL_ATTR_TRACEFILE + \li SQL_ATTR_TRACE + \li SQL_ATTR_CONNECTION_POOLING + \li SQL_ATTR_ODBC_VERSION \endlist - \i + \li \list - \i CLIENT_COMPRESS - \i CLIENT_FOUND_ROWS - \i CLIENT_IGNORE_SPACE - \i CLIENT_SSL - \i CLIENT_ODBC - \i CLIENT_NO_SCHEMA - \i CLIENT_INTERACTIVE - \i UNIX_SOCKET - \i MYSQL_OPT_RECONNECT + \li CLIENT_COMPRESS + \li CLIENT_FOUND_ROWS + \li CLIENT_IGNORE_SPACE + \li CLIENT_SSL + \li CLIENT_ODBC + \li CLIENT_NO_SCHEMA + \li CLIENT_INTERACTIVE + \li UNIX_SOCKET + \li MYSQL_OPT_RECONNECT \endlist - \i + \li \list - \i connect_timeout - \i options - \i tty - \i requiressl - \i service + \li connect_timeout + \li options + \li tty + \li requiressl + \li service \endlist - \header \i DB2 \i OCI \i TDS + \header \li DB2 \li OCI \li TDS \row - \i + \li \list - \i SQL_ATTR_ACCESS_MODE - \i SQL_ATTR_LOGIN_TIMEOUT + \li SQL_ATTR_ACCESS_MODE + \li SQL_ATTR_LOGIN_TIMEOUT \endlist - \i + \li \list - \i OCI_ATTR_PREFETCH_ROWS - \i OCI_ATTR_PREFETCH_MEMORY + \li OCI_ATTR_PREFETCH_ROWS + \li OCI_ATTR_PREFETCH_MEMORY \endlist - \i + \li \e none - \header \i SQLite \i Interbase + \header \li SQLite \li Interbase \row - \i + \li \list - \i QSQLITE_BUSY_TIMEOUT - \i QSQLITE_OPEN_READONLY - \i QSQLITE_ENABLE_SHARED_CACHE + \li QSQLITE_BUSY_TIMEOUT + \li QSQLITE_OPEN_READONLY + \li QSQLITE_ENABLE_SHARED_CACHE \endlist - \i + \li \list - \i ISC_DPB_LC_CTYPE - \i ISC_DPB_SQL_ROLE_NAME + \li ISC_DPB_LC_CTYPE + \li ISC_DPB_SQL_ROLE_NAME \endlist \endtable @@ -1354,47 +1354,47 @@ bool QSqlDatabase::isDriverAvailable(const QString& name) and their constructor arguments: \table - \header \i Driver \i Class name \i Constructor arguments \i File to include + \header \li Driver \li Class name \li Constructor arguments \li File to include \row - \i QPSQL - \i QPSQLDriver - \i PGconn *connection - \i \c qsql_psql.cpp + \li QPSQL + \li QPSQLDriver + \li PGconn *connection + \li \c qsql_psql.cpp \row - \i QMYSQL - \i QMYSQLDriver - \i MYSQL *connection - \i \c qsql_mysql.cpp + \li QMYSQL + \li QMYSQLDriver + \li MYSQL *connection + \li \c qsql_mysql.cpp \row - \i QOCI - \i QOCIDriver - \i OCIEnv *environment, OCISvcCtx *serviceContext - \i \c qsql_oci.cpp + \li QOCI + \li QOCIDriver + \li OCIEnv *environment, OCISvcCtx *serviceContext + \li \c qsql_oci.cpp \row - \i QODBC - \i QODBCDriver - \i SQLHANDLE environment, SQLHANDLE connection - \i \c qsql_odbc.cpp + \li QODBC + \li QODBCDriver + \li SQLHANDLE environment, SQLHANDLE connection + \li \c qsql_odbc.cpp \row - \i QDB2 - \i QDB2 - \i SQLHANDLE environment, SQLHANDLE connection - \i \c qsql_db2.cpp + \li QDB2 + \li QDB2 + \li SQLHANDLE environment, SQLHANDLE connection + \li \c qsql_db2.cpp \row - \i QTDS - \i QTDSDriver - \i LOGINREC *loginRecord, DBPROCESS *dbProcess, const QString &hostName - \i \c qsql_tds.cpp + \li QTDS + \li QTDSDriver + \li LOGINREC *loginRecord, DBPROCESS *dbProcess, const QString &hostName + \li \c qsql_tds.cpp \row - \i QSQLITE - \i QSQLiteDriver - \i sqlite *connection - \i \c qsql_sqlite.cpp + \li QSQLITE + \li QSQLiteDriver + \li sqlite *connection + \li \c qsql_sqlite.cpp \row - \i QIBASE - \i QIBaseDriver - \i isc_db_handle connection - \i \c qsql_ibase.cpp + \li QIBASE + \li QIBaseDriver + \li isc_db_handle connection + \li \c qsql_ibase.cpp \endtable The host name (or service name) is needed when constructing the diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index 861cd4ad0f..7e6a7f7386 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -569,22 +569,22 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, \list - \i If \a field is character data, the value is returned enclosed + \li If \a field is character data, the value is returned enclosed in single quotation marks, which is appropriate for many SQL databases. Any embedded single-quote characters are escaped (replaced with two single-quote characters). If \a trimStrings is true (the default is false), all trailing whitespace is trimmed from the field. - \i If \a field is date/time data, the value is formatted in ISO + \li If \a field is date/time data, the value is formatted in ISO format and enclosed in single quotation marks. If the date/time data is invalid, "NULL" is returned. - \i If \a field is \link QByteArray bytearray\endlink data, and the + \li If \a field is \link QByteArray bytearray\endlink data, and the driver can edit binary fields, the value is formatted as a hexadecimal string. - \i For any other field type, toString() is called on its value + \li For any other field type, toString() is called on its value and the result of this is returned. \endlist diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 3e6712b27e..e21a8f4956 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -130,11 +130,11 @@ QSqlQueryPrivate::~QSqlQueryPrivate() Navigating records is performed with the following functions: \list - \o next() - \o previous() - \o first() - \o last() - \o seek() + \li next() + \li previous() + \li first() + \li last() + \li seek() \endlist These functions allow the programmer to move forward, backward @@ -188,23 +188,23 @@ QSqlQueryPrivate::~QSqlQueryPrivate() different binding approaches, as well as one example of binding values to a stored procedure. - \bold{Named binding using named placeholders:} + \b{Named binding using named placeholders:} \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 9 - \bold{Positional binding using named placeholders:} + \b{Positional binding using named placeholders:} \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 10 - \bold{Binding values using positional placeholders (version 1):} + \b{Binding values using positional placeholders (version 1):} \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 11 - \bold{Binding values using positional placeholders (version 2):} + \b{Binding values using positional placeholders (version 2):} \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 12 - \bold{Binding values to a stored procedure:} + \b{Binding values to a stored procedure:} This code calls a stored procedure called \c AsciiToInt(), passing it a character through its in parameter, and taking its result in @@ -460,10 +460,10 @@ const QSqlResult* QSqlQuery::result() const \list - \o If \a index is negative, the result is positioned before the + \li If \a index is negative, the result is positioned before the first record and false is returned. - \o Otherwise, an attempt is made to move to the record at position + \li Otherwise, an attempt is made to move to the record at position \a index. If the record at position \a index could not be retrieved, the result is positioned after the last record and false is returned. If the record is successfully retrieved, true is returned. @@ -474,18 +474,18 @@ const QSqlResult* QSqlQuery::result() const \list - \o If the result is currently positioned before the first record or + \li If the result is currently positioned before the first record or on the first record, and \a index is negative, there is no change, and false is returned. - \o If the result is currently located after the last record, and \a + \li If the result is currently located after the last record, and \a index is positive, there is no change, and false is returned. - \o If the result is currently located somewhere in the middle, and + \li If the result is currently located somewhere in the middle, and the relative offset \a index moves the result below zero, the result is positioned before the first record and false is returned. - \o Otherwise, an attempt is made to move to the record \a index + \li Otherwise, an attempt is made to move to the record \a index records ahead of the current record (or \a index records behind the current record if \a index is negative). If the record at offset \a index could not be retrieved, the result is positioned after the @@ -571,14 +571,14 @@ bool QSqlQuery::seek(int index, bool relative) \list - \o If the result is currently located before the first record, + \li If the result is currently located before the first record, e.g. immediately after a query is executed, an attempt is made to retrieve the first record. - \o If the result is currently located after the last record, there + \li If the result is currently located after the last record, there is no change and false is returned. - \o If the result is located somewhere in the middle, an attempt is + \li If the result is located somewhere in the middle, an attempt is made to retrieve the next record. \endlist @@ -621,13 +621,13 @@ bool QSqlQuery::next() \list - \o If the result is currently located before the first record, there + \li If the result is currently located before the first record, there is no change and false is returned. - \o If the result is currently located after the last record, an + \li If the result is currently located after the last record, an attempt is made to retrieve the last record. - \o If the result is somewhere in the middle, an attempt is made to + \li If the result is somewhere in the middle, an attempt is made to retrieve the previous record. \endlist diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp index 8dd18ca1d0..3a521deea2 100644 --- a/src/sql/models/qsqlrelationaltablemodel.cpp +++ b/src/sql/models/qsqlrelationaltablemodel.cpp @@ -331,8 +331,8 @@ void QSqlRelationalTableModelPrivate::clearCache() columns to be set as foreign keys into other database tables. \table - \row \o \inlineimage noforeignkeys.png - \o \inlineimage foreignkeys.png + \row \li \inlineimage noforeignkeys.png + \li \inlineimage foreignkeys.png \endtable The screenshot on the left shows a plain QSqlTableModel in a @@ -375,14 +375,14 @@ void QSqlRelationalTableModelPrivate::clearCache() Notes: \list - \o The table must have a primary key declared. - \o The table's primary key may not contain a relation to + \li The table must have a primary key declared. + \li The table's primary key may not contain a relation to another table. - \o If a relational table contains keys that refer to non-existent + \li If a relational table contains keys that refer to non-existent rows in the referenced table, the rows containing the invalid keys will not be exposed through the model. The user or the database is responsible for keeping referential integrity. - \o If a relation's display column name is also used as a column + \li If a relation's display column name is also used as a column name in the main table, or if it is used as display column name in more than one relation it will be aliased. The alias is is the relation's table name and display column name joined @@ -393,7 +393,7 @@ void QSqlRelationalTableModelPrivate::clearCache() QSqlRelation, so QSqlRelation::displayColumn() will return the original display column name, but QSqlRecord::fieldName() will return aliases. - \o When using setData() the role should always be Qt::EditRole, + \li When using setData() the role should always be Qt::EditRole, and when using data() the role should always be Qt::DisplayRole. \endlist diff --git a/src/testlib/qsignalspy.qdoc b/src/testlib/qsignalspy.qdoc index 5fa3667d6b..dddaed74f6 100644 --- a/src/testlib/qsignalspy.qdoc +++ b/src/testlib/qsignalspy.qdoc @@ -48,7 +48,7 @@ \snippet doc/src/snippets/code/doc_src_qsignalspy.cpp 1 - \bold {Note:} Non-standard data types need to be registered, using + \b {Note:} Non-standard data types need to be registered, using the qRegisterMetaType() function, before you can create a QSignalSpy. For example: diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index e16787693d..5aac97cfab 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -109,7 +109,7 @@ QT_BEGIN_NAMESPACE true, execution continues. If not, a failure is recorded in the test log and the test won't be executed further. - \bold {Note:} This macro can only be used in a test function that is invoked + \b {Note:} This macro can only be used in a test function that is invoked by the test framework. Example: @@ -246,7 +246,7 @@ QT_BEGIN_NAMESPACE \c aString and \c expected are variables on the stack that are initialized with the current test data. - \bold {Note:} This macro can only be used in a test function that is invoked + \b {Note:} This macro can only be used in a test function that is invoked by the test framework. The test function must have a _data function. */ @@ -266,7 +266,7 @@ QT_BEGIN_NAMESPACE This macro can be used to force a test failure. The test stops executing and the failure \a message is appended to the test log. - \bold {Note:} This macro can only be used in a test function that is invoked + \b {Note:} This macro can only be used in a test function that is invoked by the test framework. Example: @@ -316,7 +316,7 @@ QT_BEGIN_NAMESPACE If called from initTestCase() or initTestCase_data(), the QSKIP() macro will skip all test and _data functions. - \bold {Note:} This macro can only be used in a test function or _data + \b {Note:} This macro can only be used in a test function or _data function that is invoked by the test framework. Example: @@ -343,7 +343,7 @@ QT_BEGIN_NAMESPACE \a mode is a \l QTest::TestFailMode and sets whether the test should continue to execute or not. - \bold {Note:} This macro can only be used in a test function that is invoked + \b {Note:} This macro can only be used in a test function that is invoked by the test framework. Example 1: @@ -379,11 +379,11 @@ QT_BEGIN_NAMESPACE resolves to an existing file or directory: \list - \o \a filename relative to QCoreApplication::applicationDirPath() + \li \a filename relative to QCoreApplication::applicationDirPath() (only if a QCoreApplication or QApplication object has been created). - \o \a filename relative to the test's standard install directory + \li \a filename relative to the test's standard install directory (QLibraryInfo::TestsPath with the lowercased testcase name appended). - \o \a filename relative to the directory containing the source file from which + \li \a filename relative to the directory containing the source file from which QFINDTESTDATA is invoked. \endlist @@ -396,16 +396,16 @@ QT_BEGIN_NAMESPACE The testdata file will be resolved as the first existing file from: \list - \o \c{/home/user/build/myxmlparser/tests/tst_myxmlparser/testxml/simple1.xml} - \o \c{/usr/local/Qt-5.0.0/tests/tst_myxmlparser/testxml/simple1.xml} - \o \c{/home/user/sources/myxmlparser/tests/tst_myxmlparser/testxml/simple1.xml} + \li \c{/home/user/build/myxmlparser/tests/tst_myxmlparser/testxml/simple1.xml} + \li \c{/usr/local/Qt-5.0.0/tests/tst_myxmlparser/testxml/simple1.xml} + \li \c{/home/user/sources/myxmlparser/tests/tst_myxmlparser/testxml/simple1.xml} \endlist This allows the test to find its testdata regardless of whether the test has been installed, and regardless of whether the test's build tree is equal to the test's source tree. - \bold {Note:} reliable detection of testdata from the source directory requires + \b {Note:} reliable detection of testdata from the source directory requires either that qmake is used, or the \c{QT_TESTCASE_BUILDDIR} macro is defined to point to the working directory from which the compiler is invoked, or only absolute paths to the source files are passed to the compiler. Otherwise, the @@ -427,7 +427,7 @@ QT_BEGIN_NAMESPACE Similarly, if qmake is used and the configuration includes \c{QT += gui}, then \c QT_GUI_LIB will be defined automatically. - \bold {Note:} On platforms that have keypad navigation enabled by default, + \b {Note:} On platforms that have keypad navigation enabled by default, this macro will forcefully disable it if \c QT_WIDGETS_LIB is defined. This is done to simplify the usage of key events when writing autotests. If you wish to write a test case that uses keypad navigation, you should enable it either in the @@ -597,7 +597,7 @@ QT_BEGIN_NAMESPACE Simulates pressing a \a key with an optional \a modifier on a \a widget. If \a delay is larger than 0, the test will wait for \a delay milliseconds before pressing the key. - \bold {Note:} At some point you should release the key using \l keyRelease(). + \b {Note:} At some point you should release the key using \l keyRelease(). \sa QTest::keyRelease(), QTest::keyClick() */ @@ -610,7 +610,7 @@ QT_BEGIN_NAMESPACE If \a delay is larger than 0, the test will wait for \a delay milliseconds before pressing the key. - \bold {Note:} At some point you should release the key using \l keyRelease(). + \b {Note:} At some point you should release the key using \l keyRelease(). \sa QTest::keyRelease(), QTest::keyClick() */ @@ -714,7 +714,7 @@ QT_BEGIN_NAMESPACE You can add specializations of this function to your test to enable verbose output. - \bold {Note:} The caller of toString() must delete the returned data + \b {Note:} The caller of toString() must delete the returned data using \c{delete[]}. Your implementation should return a string created with \c{new[]} or qstrdup(). @@ -2128,7 +2128,7 @@ void QTest::qWarn(const char *message, const char *file, int line) test log. If the test finished and the \a message was not outputted, a test failure is appended to the test log. - \bold {Note:} Invoking this function will only ignore one message. + \b {Note:} Invoking this function will only ignore one message. If the message you want to ignore is outputted twice, you have to call ignoreMessage() twice, too. @@ -2295,7 +2295,7 @@ void QTest::addColumnInternal(int id, const char *name) Example: \snippet doc/src/snippets/code/src_qtestlib_qtestcase.cpp 20 - \bold {Note:} This macro can only be used in a test's data function + \b {Note:} This macro can only be used in a test's data function that is invoked by the test framework. See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for @@ -2328,7 +2328,7 @@ QTestData &QTest::newRow(const char *dataTag) To add custom types to the testdata, the type must be registered with QMetaType via \l Q_DECLARE_METATYPE(). - \bold {Note:} This macro can only be used in a test's data function + \b {Note:} This macro can only be used in a test's data function that is invoked by the test framework. See \l {Chapter 2: Data Driven Testing}{Data Driven Testing} for @@ -2374,7 +2374,7 @@ bool QTest::currentTestFailed() \a ms must be greater than 0. - \bold {Note:} The qSleep() function calls either \c nanosleep() on + \b {Note:} The qSleep() function calls either \c nanosleep() on unix or \c Sleep() on windows, so the accuracy of time spent in qSleep() depends on the operating system. diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 5ffb5466d6..4170df4799 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -166,7 +166,7 @@ QVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const \section1 Modal Dialogs - A \bold{modal} dialog is a dialog that blocks input to other + A \b{modal} dialog is a dialog that blocks input to other visible windows in the same application. Dialogs that are used to request a file name from the user or that are used to set application preferences are usually modal. Dialogs can be @@ -200,7 +200,7 @@ QVariant QDialogPrivate::styleHint(QPlatformDialogHelper::StyleHint hint) const \section1 Modeless Dialogs - A \bold{modeless} dialog is a dialog that operates + A \b{modeless} dialog is a dialog that operates independently of other windows in the same application. Find and replace dialogs in word-processors are often modeless to allow the user to interact with both the application's main window and with diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 84fdef6702..3908daec9c 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1096,7 +1096,7 @@ QStringList qt_make_filter_list(const QString &filter) Sets the filter used in the file dialog to the given \a filter. If \a filter contains a pair of parentheses containing one or more - of \bold{anything*something}, separated by spaces, then only the + of \b{anything*something}, separated by spaces, then only the text contained in the parentheses is used as the filter. This means that these calls are all equivalent: diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 0211b2512c..5446eca383 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -130,12 +130,12 @@ QT_BEGIN_NAMESPACE \fn bool QFileSystemModel::rmdir(const QModelIndex &index) const Removes the directory corresponding to the model item \a index in the - file system model and \bold{deletes the corresponding directory from the + file system model and \b{deletes the corresponding directory from the file system}, returning true if successful. If the directory cannot be removed, false is returned. \warning This function deletes directories from the file system; it does - \bold{not} move them to a location where they can be recovered. + \b{not} move them to a location where they can be recovered. \sa remove() */ @@ -185,11 +185,11 @@ QT_BEGIN_NAMESPACE /*! \fn bool QFileSystemModel::remove(const QModelIndex &index) const - Removes the model item \a index from the file system model and \bold{deletes the + Removes the model item \a index from the file system model and \b{deletes the corresponding file from the file system}, returning true if successful. If the item cannot be removed, false is returned. - \warning This function deletes files from the file system; it does \bold{not} + \warning This function deletes files from the file system; it does \b{not} move them to a location where they can be recovered. \sa rmdir() diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp index 9cf41003f5..737d6bb467 100644 --- a/src/widgets/dialogs/qinputdialog.cpp +++ b/src/widgets/dialogs/qinputdialog.cpp @@ -1031,10 +1031,10 @@ QString QInputDialog::cancelButtonText() const in \a member. These are: \list - \o textValueSelected() if \a member has a QString for its first argument. - \o intValueSelected() if \a member has an int for its first argument. - \o doubleValueSelected() if \a member has a double for its first argument. - \o accepted() if \a member has NO arguments. + \li textValueSelected() if \a member has a QString for its first argument. + \li intValueSelected() if \a member has an int for its first argument. + \li doubleValueSelected() if \a member has a double for its first argument. + \li accepted() if \a member has NO arguments. \endlist The signal will be disconnected from the slot when the dialog is closed. diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index a737584e3f..3909125fe7 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -577,21 +577,21 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button) \table \row - \o \img qmessagebox-quest.png - \o \l Question - \o For asking a question during normal operations. + \li \img qmessagebox-quest.png + \li \l Question + \li For asking a question during normal operations. \row - \o \img qmessagebox-info.png - \o \l Information - \o For reporting information about normal operations. + \li \img qmessagebox-info.png + \li \l Information + \li For reporting information about normal operations. \row - \o \img qmessagebox-warn.png - \o \l Warning - \o For reporting non-critical errors. + \li \img qmessagebox-warn.png + \li \l Warning + \li For reporting non-critical errors. \row - \o \img qmessagebox-crit.png - \o \l Critical - \o For reporting critical errors. + \li \img qmessagebox-crit.png + \li \l Critical + \li For reporting critical errors. \endtable \l{QMessageBox::Icon}{Predefined icons} are not defined by QMessageBox, but @@ -663,13 +663,13 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button) \list 1 - \o If there is only one button, it is the button activated when + \li If there is only one button, it is the button activated when \key Esc is pressed. - \o If there is a \l Cancel button, it is the button activated when + \li If there is a \l Cancel button, it is the button activated when \key Esc is pressed. - \o If there is exactly one button having either + \li If there is exactly one button having either \l{QMessageBox::RejectRole} {the Reject role} or the \l{QMessageBox::NoRole} {the No role}, it is the button activated when \key Esc is pressed. @@ -927,9 +927,9 @@ QAbstractButton *QMessageBox::button(StandardButton which) const escape button as follows: \list 1 - \o If there is only one button, it is made the escape button. - \o If there is a \l Cancel button, it is made the escape button. - \o On Mac OS X only, if there is exactly one button with the role + \li If there is only one button, it is made the escape button. + \li If there is a \l Cancel button, it is made the escape button. + \li On Mac OS X only, if there is exactly one button with the role QMessageBox::RejectRole, it is made the escape button. \endlist @@ -1142,11 +1142,11 @@ void QMessageBox::setText(const QString &text) values: \list - \o QMessageBox::NoIcon - \o QMessageBox::Question - \o QMessageBox::Information - \o QMessageBox::Warning - \o QMessageBox::Critical + \li QMessageBox::NoIcon + \li QMessageBox::Question + \li QMessageBox::Information + \li QMessageBox::Warning + \li QMessageBox::Critical \endlist The default is QMessageBox::NoIcon. @@ -1649,12 +1649,12 @@ QMessageBox::StandardButton QMessageBox::critical(QWidget *parent, const QString about() looks for a suitable icon in four locations: \list 1 - \o It prefers \link QWidget::windowIcon() parent->icon() \endlink + \li It prefers \link QWidget::windowIcon() parent->icon() \endlink if that exists. - \o If not, it tries the top-level widget containing \a parent. - \o If that fails, it tries the \link + \li If not, it tries the top-level widget containing \a parent. + \li If that fails, it tries the \link QApplication::activeWindow() active window. \endlink - \o As a last resort it uses the Information icon. + \li As a last resort it uses the Information icon. \endlist The about box has a single button labelled "OK". On Mac OS X, the @@ -1929,26 +1929,26 @@ void QMessageBoxPrivate::retranslateStrings() The \a icon must be one of the following: \list - \o QMessageBox::NoIcon - \o QMessageBox::Question - \o QMessageBox::Information - \o QMessageBox::Warning - \o QMessageBox::Critical + \li QMessageBox::NoIcon + \li QMessageBox::Question + \li QMessageBox::Information + \li QMessageBox::Warning + \li QMessageBox::Critical \endlist Each button, \a button0, \a button1 and \a button2, can have one of the following values: \list - \o QMessageBox::NoButton - \o QMessageBox::Ok - \o QMessageBox::Cancel - \o QMessageBox::Yes - \o QMessageBox::No - \o QMessageBox::Abort - \o QMessageBox::Retry - \o QMessageBox::Ignore - \o QMessageBox::YesAll - \o QMessageBox::NoAll + \li QMessageBox::NoButton + \li QMessageBox::Ok + \li QMessageBox::Cancel + \li QMessageBox::Yes + \li QMessageBox::No + \li QMessageBox::Abort + \li QMessageBox::Retry + \li QMessageBox::Ignore + \li QMessageBox::YesAll + \li QMessageBox::NoAll \endlist Use QMessageBox::NoButton for the later parameters to have fewer @@ -1994,16 +1994,16 @@ QMessageBox::QMessageBox(const QString &title, const QString &text, Icon icon, of the following values: \list - \o QMessageBox::NoButton - \o QMessageBox::Ok - \o QMessageBox::Cancel - \o QMessageBox::Yes - \o QMessageBox::No - \o QMessageBox::Abort - \o QMessageBox::Retry - \o QMessageBox::Ignore - \o QMessageBox::YesAll - \o QMessageBox::NoAll + \li QMessageBox::NoButton + \li QMessageBox::Ok + \li QMessageBox::Cancel + \li QMessageBox::Yes + \li QMessageBox::No + \li QMessageBox::Abort + \li QMessageBox::Retry + \li QMessageBox::Ignore + \li QMessageBox::YesAll + \li QMessageBox::NoAll \endlist If you don't want all three buttons, set the last button, or last @@ -2080,16 +2080,16 @@ int QMessageBox::information(QWidget *parent, const QString &title, const QStrin following values: \list - \o QMessageBox::NoButton - \o QMessageBox::Ok - \o QMessageBox::Cancel - \o QMessageBox::Yes - \o QMessageBox::No - \o QMessageBox::Abort - \o QMessageBox::Retry - \o QMessageBox::Ignore - \o QMessageBox::YesAll - \o QMessageBox::NoAll + \li QMessageBox::NoButton + \li QMessageBox::Ok + \li QMessageBox::Cancel + \li QMessageBox::Yes + \li QMessageBox::No + \li QMessageBox::Abort + \li QMessageBox::Retry + \li QMessageBox::Ignore + \li QMessageBox::YesAll + \li QMessageBox::NoAll \endlist If you don't want all three buttons, set the last button, or last @@ -2166,16 +2166,16 @@ int QMessageBox::question(QWidget *parent, const QString &title, const QString& one of the following values: \list - \o QMessageBox::NoButton - \o QMessageBox::Ok - \o QMessageBox::Cancel - \o QMessageBox::Yes - \o QMessageBox::No - \o QMessageBox::Abort - \o QMessageBox::Retry - \o QMessageBox::Ignore - \o QMessageBox::YesAll - \o QMessageBox::NoAll + \li QMessageBox::NoButton + \li QMessageBox::Ok + \li QMessageBox::Cancel + \li QMessageBox::Yes + \li QMessageBox::No + \li QMessageBox::Abort + \li QMessageBox::Retry + \li QMessageBox::Ignore + \li QMessageBox::YesAll + \li QMessageBox::NoAll \endlist If you don't want all three buttons, set the last button, or last @@ -2251,16 +2251,16 @@ int QMessageBox::warning(QWidget *parent, const QString &title, const QString& t one of the following values: \list - \o QMessageBox::NoButton - \o QMessageBox::Ok - \o QMessageBox::Cancel - \o QMessageBox::Yes - \o QMessageBox::No - \o QMessageBox::Abort - \o QMessageBox::Retry - \o QMessageBox::Ignore - \o QMessageBox::YesAll - \o QMessageBox::NoAll + \li QMessageBox::NoButton + \li QMessageBox::Ok + \li QMessageBox::Cancel + \li QMessageBox::Yes + \li QMessageBox::No + \li QMessageBox::Abort + \li QMessageBox::Retry + \li QMessageBox::Ignore + \li QMessageBox::YesAll + \li QMessageBox::NoAll \endlist If you don't want all three buttons, set the last button, or last diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp index f39a7b63ec..350fb57e20 100644 --- a/src/widgets/dialogs/qprogressdialog.cpp +++ b/src/widgets/dialogs/qprogressdialog.cpp @@ -281,10 +281,10 @@ void QProgressDialogPrivate::_q_disconnectOnClose() Default settings: \list - \i The label text is empty. - \i The cancel button text is (translated) "Cancel". - \i minimum is 0; - \i maximum is 100 + \li The label text is empty. + \li The cancel button text is (translated) "Cancel". + \li minimum is 0; + \li maximum is 100 \endlist The \a parent argument is dialog's parent widget. The widget flags, \a f, are diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 8cd3799cae..8a75353c86 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -1826,28 +1826,28 @@ void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *) QWizard supports four wizard looks: \list - \o ClassicStyle - \o ModernStyle - \o MacStyle - \o AeroStyle + \li ClassicStyle + \li ModernStyle + \li MacStyle + \li AeroStyle \endlist You can explicitly set the look to use using setWizardStyle() (e.g., if you want the same look on all platforms). \table - \header \o ClassicStyle - \o ModernStyle - \o MacStyle - \o AeroStyle - \row \o \inlineimage qtwizard-classic1.png - \o \inlineimage qtwizard-modern1.png - \o \inlineimage qtwizard-mac1.png - \o \inlineimage qtwizard-aero1.png - \row \o \inlineimage qtwizard-classic2.png - \o \inlineimage qtwizard-modern2.png - \o \inlineimage qtwizard-mac2.png - \o \inlineimage qtwizard-aero2.png + \header \li ClassicStyle + \li ModernStyle + \li MacStyle + \li AeroStyle + \row \li \inlineimage qtwizard-classic1.png + \li \inlineimage qtwizard-modern1.png + \li \inlineimage qtwizard-mac1.png + \li \inlineimage qtwizard-aero1.png + \row \li \inlineimage qtwizard-classic2.png + \li \inlineimage qtwizard-modern2.png + \li \inlineimage qtwizard-mac2.png + \li \inlineimage qtwizard-aero2.png \endtable Note: AeroStyle has effect only on a Windows Vista system with alpha compositing enabled. @@ -1876,15 +1876,15 @@ void QWizardAntiFlickerWidget::paintEvent(QPaintEvent *) only one page is shown. A page has the following attributes: \list - \o A \l{QWizardPage::}{title}. - \o A \l{QWizardPage::}{subTitle}. - \o A set of pixmaps, which may or may not be honored, depending + \li A \l{QWizardPage::}{title}. + \li A \l{QWizardPage::}{subTitle}. + \li A set of pixmaps, which may or may not be honored, depending on the wizard's style: \list - \o WatermarkPixmap (used by ClassicStyle and ModernStyle) - \o BannerPixmap (used by ModernStyle) - \o LogoPixmap (used by ClassicStyle and ModernStyle) - \o BackgroundPixmap (used by MacStyle) + \li WatermarkPixmap (used by ClassicStyle and ModernStyle) + \li BannerPixmap (used by ModernStyle) + \li LogoPixmap (used by ClassicStyle and ModernStyle) + \li BackgroundPixmap (used by MacStyle) \endlist \endlist @@ -2590,9 +2590,9 @@ bool QWizard::testOption(WizardOption option) const By default, the following options are set (depending on the platform): \list - \o Windows: HelpButtonOnRight. - \o Mac OS X: NoDefaultButton and NoCancelButton. - \o X11 and QWS (Qt for Embedded Linux): none. + \li Windows: HelpButtonOnRight. + \li Mac OS X: NoDefaultButton and NoCancelButton. + \li X11 and QWS (Qt for Embedded Linux): none. \endlist \sa wizardStyle @@ -2881,14 +2881,14 @@ QPixmap QWizard::pixmap(WizardPixmap which) const changedSignal. The table below lists these widgets: \table - \header \o Widget \o Property \o Change Notification Signal - \row \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()} - \row \o QAbstractSlider \o int \l{QAbstractSlider::}{value} \o \l{QAbstractSlider::}{valueChanged()} - \row \o QComboBox \o int \l{QComboBox::}{currentIndex} \o \l{QComboBox::}{currentIndexChanged()} - \row \o QDateTimeEdit \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()} - \row \o QLineEdit \o QString \l{QLineEdit::}{text} \o \l{QLineEdit::}{textChanged()} - \row \o QListWidget \o int \l{QListWidget::}{currentRow} \o \l{QListWidget::}{currentRowChanged()} - \row \o QSpinBox \o int \l{QSpinBox::}{value} \o \l{QSpinBox::}{valueChanged()} + \header \li Widget \li Property \li Change Notification Signal + \row \li QAbstractButton \li bool \l{QAbstractButton::}{checked} \li \l{QAbstractButton::}{toggled()} + \row \li QAbstractSlider \li int \l{QAbstractSlider::}{value} \li \l{QAbstractSlider::}{valueChanged()} + \row \li QComboBox \li int \l{QComboBox::}{currentIndex} \li \l{QComboBox::}{currentIndexChanged()} + \row \li QDateTimeEdit \li QDateTime \l{QDateTimeEdit::}{dateTime} \li \l{QDateTimeEdit::}{dateTimeChanged()} + \row \li QLineEdit \li QString \l{QLineEdit::}{text} \li \l{QLineEdit::}{textChanged()} + \row \li QListWidget \li int \l{QListWidget::}{currentRow} \li \l{QListWidget::}{currentRowChanged()} + \row \li QSpinBox \li int \l{QSpinBox::}{value} \li \l{QSpinBox::}{valueChanged()} \endtable \sa QWizardPage::registerField() @@ -3361,19 +3361,19 @@ int QWizard::nextId() const provide custom behavior: \list - \o initializePage() is called to initialize the page's contents + \li initializePage() is called to initialize the page's contents when the user clicks the wizard's \gui Next button. If you want to derive the page's default from what the user entered on previous pages, this is the function to reimplement. - \o cleanupPage() is called to reset the page's contents when the + \li cleanupPage() is called to reset the page's contents when the user clicks the wizard's \gui Back button. - \o validatePage() validates the page when the user clicks \gui + \li validatePage() validates the page when the user clicks \gui Next or \gui Finish. It is often used to show an error message if the user has entered incomplete or invalid information. - \o nextId() returns the ID of the next page. It is useful when + \li nextId() returns the ID of the next page. It is useful when \l{creating non-linear wizards}, which allow different traversal paths based on the information provided by the user. - \o isComplete() is called to determine whether the \gui Next + \li isComplete() is called to determine whether the \gui Next and/or \gui Finish button should be enabled or disabled. If you reimplement isComplete(), also make sure that completeChanged() is emitted whenever the complete state @@ -3878,14 +3878,14 @@ QVariant QWizardPage::field(const QString &name) const changedSignal. The table below lists these widgets: \table - \header \o Widget \o Property \o Change Notification Signal - \row \o QAbstractButton \o bool \l{QAbstractButton::}{checked} \o \l{QAbstractButton::}{toggled()} - \row \o QAbstractSlider \o int \l{QAbstractSlider::}{value} \o \l{QAbstractSlider::}{valueChanged()} - \row \o QComboBox \o int \l{QComboBox::}{currentIndex} \o \l{QComboBox::}{currentIndexChanged()} - \row \o QDateTimeEdit \o QDateTime \l{QDateTimeEdit::}{dateTime} \o \l{QDateTimeEdit::}{dateTimeChanged()} - \row \o QLineEdit \o QString \l{QLineEdit::}{text} \o \l{QLineEdit::}{textChanged()} - \row \o QListWidget \o int \l{QListWidget::}{currentRow} \o \l{QListWidget::}{currentRowChanged()} - \row \o QSpinBox \o int \l{QSpinBox::}{value} \o \l{QSpinBox::}{valueChanged()} + \header \li Widget \li Property \li Change Notification Signal + \row \li QAbstractButton \li bool \l{QAbstractButton::}{checked} \li \l{QAbstractButton::}{toggled()} + \row \li QAbstractSlider \li int \l{QAbstractSlider::}{value} \li \l{QAbstractSlider::}{valueChanged()} + \row \li QComboBox \li int \l{QComboBox::}{currentIndex} \li \l{QComboBox::}{currentIndexChanged()} + \row \li QDateTimeEdit \li QDateTime \l{QDateTimeEdit::}{dateTime} \li \l{QDateTimeEdit::}{dateTimeChanged()} + \row \li QLineEdit \li QString \l{QLineEdit::}{text} \li \l{QLineEdit::}{textChanged()} + \row \li QListWidget \li int \l{QListWidget::}{currentRow} \li \l{QListWidget::}{currentRowChanged()} + \row \li QSpinBox \li int \l{QSpinBox::}{value} \li \l{QSpinBox::}{valueChanged()} \endtable You can use QWizard::setDefaultProperty() to add entries to this diff --git a/src/widgets/effects/qgraphicseffect.cpp b/src/widgets/effects/qgraphicseffect.cpp index f1b4cc80f9..80c0aff492 100644 --- a/src/widgets/effects/qgraphicseffect.cpp +++ b/src/widgets/effects/qgraphicseffect.cpp @@ -62,21 +62,21 @@ Qt provides the following standard effects: \list - \o QGraphicsBlurEffect - blurs the item by a given radius - \o QGraphicsDropShadowEffect - renders a dropshadow behind the item - \o QGraphicsColorizeEffect - renders the item in shades of any given color - \o QGraphicsOpacityEffect - renders the item with an opacity + \li QGraphicsBlurEffect - blurs the item by a given radius + \li QGraphicsDropShadowEffect - renders a dropshadow behind the item + \li QGraphicsColorizeEffect - renders the item in shades of any given color + \li QGraphicsOpacityEffect - renders the item with an opacity \endlist \table \row - \o{2,1} \img graphicseffect-plain.png + \li{2,1} \img graphicseffect-plain.png \row - \o \img graphicseffect-blur.png - \o \img graphicseffect-colorize.png + \li \img graphicseffect-blur.png + \li \img graphicseffect-colorize.png \row - \o \img graphicseffect-opacity.png - \o \img graphicseffect-drop-shadow.png + \li \img graphicseffect-opacity.png + \li \img graphicseffect-drop-shadow.png \endtable \img graphicseffect-widget.png diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout.cpp index 1ccf6fcffe..348d8f2d09 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout.cpp @@ -107,11 +107,11 @@ avoid any future regressions in behaviour: \list - \o Stretch factors are not respected. + \li Stretch factors are not respected. - \o QSizePolicy::ExpandFlag is not respected. + \li QSizePolicy::ExpandFlag is not respected. - \o Height for width is not respected. + \li Height for width is not respected. \endlist diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index ab03ff7a9e..d88183fbb5 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -59,14 +59,14 @@ common shapes. These are: \list - \o QGraphicsEllipseItem provides an ellipse item - \o QGraphicsLineItem provides a line item - \o QGraphicsPathItem provides an arbitrary path item - \o QGraphicsPixmapItem provides a pixmap item - \o QGraphicsPolygonItem provides a polygon item - \o QGraphicsRectItem provides a rectangular item - \o QGraphicsSimpleTextItem provides a simple text label item - \o QGraphicsTextItem provides an advanced text browser item + \li QGraphicsEllipseItem provides an ellipse item + \li QGraphicsLineItem provides a line item + \li QGraphicsPathItem provides an arbitrary path item + \li QGraphicsPixmapItem provides a pixmap item + \li QGraphicsPolygonItem provides a polygon item + \li QGraphicsRectItem provides a rectangular item + \li QGraphicsSimpleTextItem provides a simple text label item + \li QGraphicsTextItem provides an advanced text browser item \endlist All of an item's geometric information is based on its local coordinate @@ -112,12 +112,12 @@ \list 1 - \o Reimplement shape() to return an accurate shape for your item, + \li Reimplement shape() to return an accurate shape for your item, and rely on the default implementation of collidesWithItem() to do shape-shape intersection. This can be rather expensive if the shapes are complex. - \o Reimplement collidesWithItem() to provide your own custom item + \li Reimplement collidesWithItem() to provide your own custom item and shape collision algorithm. \endlist @@ -165,10 +165,10 @@ QGraphicsItem always applies the properties in a fixed, defined order: \list - \o The item's base transform is applied (transform()) - \o The item's transformations list is applied in order (transformations()) - \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint()) - \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint()) + \li The item's base transform is applied (transform()) + \li The item's transformations list is applied in order (transformations()) + \li The item is rotated relative to its transform origin point (rotation(), transformOriginPoint()) + \li The item is scaled relative to its transform origin point (scale(), transformOriginPoint()) \endlist \section1 Painting @@ -215,14 +215,14 @@ For advanced users, there are ways to alter how your items are sorted: \list - \o You can call setZValue() on an item to explicitly stack it on top of, or + \li You can call setZValue() on an item to explicitly stack it on top of, or under, other sibling items. The default Z value for an item is 0. Items with the same Z value are stacked by insertion order. - \o You can call stackBefore() to reorder the list of children. This will + \li You can call stackBefore() to reorder the list of children. This will directly modify the insertion order. - \o You can set the ItemStacksBehindParent flag to stack a child item behind + \li You can set the ItemStacksBehindParent flag to stack a child item behind its parent. \endlist @@ -238,13 +238,13 @@ to a set of convenience event handlers: \list - \o contextMenuEvent() handles context menu events - \o focusInEvent() and focusOutEvent() handle focus in and out events - \o hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles + \li contextMenuEvent() handles context menu events + \li focusInEvent() and focusOutEvent() handle focus in and out events + \li hoverEnterEvent(), hoverMoveEvent(), and hoverLeaveEvent() handles hover enter, move and leave events - \o inputMethodEvent() handles input events, for accessibility support - \o keyPressEvent() and keyReleaseEvent() handle key press and release events - \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and + \li inputMethodEvent() handles input events, for accessibility support + \li keyPressEvent() and keyReleaseEvent() handle key press and release events + \li mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and mouseDoubleClickEvent() handles mouse press, move, release, click and doubleclick events \endlist @@ -3469,11 +3469,11 @@ QGraphicsItem *QGraphicsItem::focusScopeItem() const following events occurs: \list - \o The item becomes invisible - \o The item is removed from the scene - \o The item is deleted - \o The item call ungrabMouse() - \o Another item calls grabMouse(); the item will regain the mouse grab + \li The item becomes invisible + \li The item is removed from the scene + \li The item is deleted + \li The item call ungrabMouse() + \li Another item calls grabMouse(); the item will regain the mouse grab when the other item calls ungrabMouse(). \endlist @@ -3531,11 +3531,11 @@ void QGraphicsItem::ungrabMouse() following events occur: \list - \o The item becomes invisible - \o The item is removed from the scene - \o The item is deleted - \o The item calls ungrabKeyboard() - \o Another item calls grabKeyboard(); the item will regain the keyboard grab + \li The item becomes invisible + \li The item is removed from the scene + \li The item is deleted + \li The item calls ungrabKeyboard() + \li Another item calls grabKeyboard(); the item will regain the keyboard grab when the other item calls ungrabKeyboard(). \endlist @@ -5730,7 +5730,7 @@ void QGraphicsItem::update(const QRectF &rect) viewport, which does not benefit from scroll optimizations), this function is equivalent to calling update(\a rect). - \bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache + \b{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache is enabled; in all other cases calling this function is equivalent to calling update(\a rect). If you for sure know that the item is opaque and not overlapped by other items, you can map the \a rect to viewport coordinates and scroll the @@ -8652,8 +8652,8 @@ QVariant QGraphicsRectItem::extension(const QVariant &variant) const \table \row - \o \inlineimage graphicsview-ellipseitem.png - \o \inlineimage graphicsview-ellipseitem-pie.png + \li \inlineimage graphicsview-ellipseitem.png + \li \inlineimage graphicsview-ellipseitem-pie.png \endtable To set the item's ellipse, pass a QRectF to QGraphicsEllipseItem's diff --git a/src/widgets/graphicsview/qgraphicslayout.cpp b/src/widgets/graphicsview/qgraphicslayout.cpp index 63f04f67bc..6f93dd511d 100644 --- a/src/widgets/graphicsview/qgraphicslayout.cpp +++ b/src/widgets/graphicsview/qgraphicslayout.cpp @@ -77,19 +77,19 @@ QT_BEGIN_NAMESPACE minimum: \table - \header \o Function \o Description - \row \o QGraphicsLayoutItem::setGeometry() - \o Notifies you when the geometry of the layout is set. You can + \header \li Function \li Description + \row \li QGraphicsLayoutItem::setGeometry() + \li Notifies you when the geometry of the layout is set. You can store the geometry in your own layout class in a reimplementation of this function. - \row \o QGraphicsLayoutItem::sizeHint() - \o Returns the layout's size hints. - \row \o QGraphicsLayout::count() - \o Returns the number of items in your layout. - \row \o QGraphicsLayout::itemAt() - \o Returns a pointer to an item in your layout. - \row \o QGraphicsLayout::removeAt() - \o Removes an item from your layout without destroying it. + \row \li QGraphicsLayoutItem::sizeHint() + \li Returns the layout's size hints. + \row \li QGraphicsLayout::count() + \li Returns the number of items in your layout. + \row \li QGraphicsLayout::itemAt() + \li Returns a pointer to an item in your layout. + \row \li QGraphicsLayout::removeAt() + \li Removes an item from your layout without destroying it. \endtable For more details on how to implement each function, refer to the individual diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index d532c4e541..4cda3e51fb 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -136,45 +136,45 @@ QT_BEGIN_NAMESPACE QGraphicsProxyWidget maintains symmetry for the following states: \table - \header \o QWidget state \o QGraphicsProxyWidget state \o Notes - \row \o QWidget::enabled - \o QGraphicsProxyWidget::enabled - \o - \row \o QWidget::visible - \o QGraphicsProxyWidget::visible - \o The explicit state is also symmetric. - \row \o QWidget::geometry - \o QGraphicsProxyWidget::geometry - \o Geometry is only guaranteed to be symmetric while + \header \li QWidget state \li QGraphicsProxyWidget state \li Notes + \row \li QWidget::enabled + \li QGraphicsProxyWidget::enabled + \li + \row \li QWidget::visible + \li QGraphicsProxyWidget::visible + \li The explicit state is also symmetric. + \row \li QWidget::geometry + \li QGraphicsProxyWidget::geometry + \li Geometry is only guaranteed to be symmetric while the embedded widget is visible. - \row \o QWidget::layoutDirection - \o QGraphicsProxyWidget::layoutDirection - \o - \row \o QWidget::style - \o QGraphicsProxyWidget::style - \o - \row \o QWidget::palette - \o QGraphicsProxyWidget::palette - \o - \row \o QWidget::font - \o QGraphicsProxyWidget::font - \o - \row \o QWidget::cursor - \o QGraphicsProxyWidget::cursor - \o The embedded widget overrides the proxy widget + \row \li QWidget::layoutDirection + \li QGraphicsProxyWidget::layoutDirection + \li + \row \li QWidget::style + \li QGraphicsProxyWidget::style + \li + \row \li QWidget::palette + \li QGraphicsProxyWidget::palette + \li + \row \li QWidget::font + \li QGraphicsProxyWidget::font + \li + \row \li QWidget::cursor + \li QGraphicsProxyWidget::cursor + \li The embedded widget overrides the proxy widget cursor. The proxy cursor changes depending on which embedded subwidget is currently under the mouse. - \row \o QWidget::sizeHint() - \o QGraphicsProxyWidget::sizeHint() - \o All size hint functionality from the embedded + \row \li QWidget::sizeHint() + \li QGraphicsProxyWidget::sizeHint() + \li All size hint functionality from the embedded widget is forwarded by the proxy. - \row \o QWidget::getContentsMargins() - \o QGraphicsProxyWidget::getContentsMargins() - \o Updated once by setWidget(). - \row \o QWidget::windowTitle - \o QGraphicsProxyWidget::windowTitle - \o Updated once by setWidget(). + \row \li QWidget::getContentsMargins() + \li QGraphicsProxyWidget::getContentsMargins() + \li Updated once by setWidget(). + \row \li QWidget::windowTitle + \li QGraphicsProxyWidget::windowTitle + \li Updated once by setWidget(). \endtable \note QGraphicsScene keeps the embedded widget in a special state that diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 51d86dadb1..015cd254d4 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -3118,12 +3118,12 @@ bool QGraphicsScene::stickyFocus() const the following events occur: \list - \o If the item receives a mouse release event when there are no other + \li If the item receives a mouse release event when there are no other buttons pressed, it loses the mouse grab. - \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}), + \li If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}), or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false)}), it loses the mouse grab. - \o If the item is removed from the scene, it loses the mouse grab. + \li If the item is removed from the scene, it loses the mouse grab. \endlist If the item loses its mouse grab, the scene will ignore all mouse events diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index c179aeff2b..da4ccb1a33 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -81,10 +81,10 @@ QT_BEGIN_NAMESPACE over QGraphicsItem. It is similar to QWidget in many ways: \list - \o Provides a \l palette, a \l font and a \l style(). - \o Has a defined geometry(). - \o Supports layouts with setLayout() and layout(). - \o Supports shortcuts and actions with grabShortcut() and insertAction() + \li Provides a \l palette, a \l font and a \l style(). + \li Has a defined geometry(). + \li Supports layouts with setLayout() and layout(). + \li Supports shortcuts and actions with grabShortcut() and insertAction() \endlist Unlike QGraphicsItem, QGraphicsWidget is not an abstract class; you can @@ -106,23 +106,23 @@ QT_BEGIN_NAMESPACE Noticeable differences between QGraphicsWidget and QWidget are: \table - \header \o QGraphicsWidget - \o QWidget - \row \o Coordinates and geometry are defined with qreals (doubles or + \header \li QGraphicsWidget + \li QWidget + \row \li Coordinates and geometry are defined with qreals (doubles or floats, depending on the platform). - \o QWidget uses integer geometry (QPoint, QRect). - \row \o The widget is already visible by default; you do not have to + \li QWidget uses integer geometry (QPoint, QRect). + \row \li The widget is already visible by default; you do not have to call show() to display the widget. - \o QWidget is hidden by default until you call show(). - \row \o A subset of widget attributes are supported. - \o All widget attributes are supported. - \row \o A top-level item's style defaults to QGraphicsScene::style - \o A top-level widget's style defaults to QApplication::style - \row \o Graphics View provides a custom drag and drop framework, different + \li QWidget is hidden by default until you call show(). + \row \li A subset of widget attributes are supported. + \li All widget attributes are supported. + \row \li A top-level item's style defaults to QGraphicsScene::style + \li A top-level widget's style defaults to QApplication::style + \row \li Graphics View provides a custom drag and drop framework, different from QWidget. - \o Standard drag and drop framework. - \row \o Widget items do not support modality. - \o Full modality support. + \li Standard drag and drop framework. + \row \li Widget items do not support modality. + \li Full modality support. \endtable QGraphicsWidget supports a subset of Qt's widget attributes, @@ -130,32 +130,32 @@ QT_BEGIN_NAMESPACE listed in this table are unsupported, or otherwise unused. \table - \header \o Widget Attribute \o Usage - \row \o Qt::WA_SetLayoutDirection - \o Set by setLayoutDirection(), cleared by + \header \li Widget Attribute \li Usage + \row \li Qt::WA_SetLayoutDirection + \li Set by setLayoutDirection(), cleared by unsetLayoutDirection(). You can test this attribute to check if the widget has been explicitly assigned a \l{QGraphicsWidget::layoutDirection()} {layoutDirection}. If the attribute is not set, the \l{QGraphicsWidget::layoutDirection()} {layoutDirection()} is inherited. - \row \o Qt::WA_RightToLeft - \o Toggled by setLayoutDirection(). Inherited from the + \row \li Qt::WA_RightToLeft + \li Toggled by setLayoutDirection(). Inherited from the parent/scene. If set, the widget's layout will order horizontally arranged widgets from right to left. - \row \o Qt::WA_SetStyle - \o Set and cleared by setStyle(). If this attribute is + \row \li Qt::WA_SetStyle + \li Set and cleared by setStyle(). If this attribute is set, the widget has been explicitly assigned a style. If it is unset, the widget will use the scene's or the application's style. - \row \o Qt::WA_Resized - \o Set by setGeometry() and resize(). - \row \o Qt::WA_SetPalette - \o Set by setPalette(). - \row \o Qt::WA_SetFont - \o Set by setFont(). - \row \o Qt::WA_WindowPropagation - \o Enables propagation to window widgets. + \row \li Qt::WA_Resized + \li Set by setGeometry() and resize(). + \row \li Qt::WA_SetPalette + \li Set by setPalette(). + \row \li Qt::WA_SetFont + \li Set by setFont(). + \row \li Qt::WA_WindowPropagation + \li Enables propagation to window widgets. \endtable Although QGraphicsWidget inherits from both QObject and QGraphicsItem, @@ -646,29 +646,29 @@ QRectF QGraphicsWidget::windowFrameRect() const \table \header - \o Style Option Property - \o Value + \li Style Option Property + \li Value \row - \o state & QStyle::State_Enabled - \o Corresponds to QGraphicsItem::isEnabled(). + \li state & QStyle::State_Enabled + \li Corresponds to QGraphicsItem::isEnabled(). \row - \o state & QStyle::State_HasFocus - \o Corresponds to QGraphicsItem::hasFocus(). + \li state & QStyle::State_HasFocus + \li Corresponds to QGraphicsItem::hasFocus(). \row - \o state & QStyle::State_MouseOver - \o Corresponds to QGraphicsItem::isUnderMouse(). + \li state & QStyle::State_MouseOver + \li Corresponds to QGraphicsItem::isUnderMouse(). \row - \o direction - \o Corresponds to QGraphicsWidget::layoutDirection(). + \li direction + \li Corresponds to QGraphicsWidget::layoutDirection(). \row - \o rect - \o Corresponds to QGraphicsWidget::rect().toRect(). + \li rect + \li Corresponds to QGraphicsWidget::rect().toRect(). \row - \o palette - \o Corresponds to QGraphicsWidget::palette(). + \li palette + \li Corresponds to QGraphicsWidget::palette(). \row - \o fontMetrics - \o Corresponds to QFontMetrics(QGraphicsWidget::font()). + \li fontMetrics + \li Corresponds to QFontMetrics(QGraphicsWidget::font()). \endtable Subclasses of QGraphicsWidget should call the base implementation, and @@ -1201,11 +1201,11 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant & QGraphicsWidget delivers notifications for the following properties: - \table \o propertyName \o Property - \row \o layoutDirection \o QGraphicsWidget::layoutDirection - \row \o size \o QGraphicsWidget::size - \row \o font \o QGraphicsWidget::font - \row \o palette \o QGraphicsWidget::palette + \table \li propertyName \li Property + \row \li layoutDirection \li QGraphicsWidget::layoutDirection + \row \li size \li QGraphicsWidget::size + \row \li font \li QGraphicsWidget::font + \row \li palette \li QGraphicsWidget::palette \endtable \sa itemChange() @@ -1347,33 +1347,33 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) Handles the \a event. QGraphicsWidget handles the following events: - \table \o Event \o Usage - \row \o Polish - \o Delivered to the widget some time after it has been + \table \li Event \li Usage + \row \li Polish + \li Delivered to the widget some time after it has been shown. - \row \o GraphicsSceneMove - \o Delivered to the widget after its local position has + \row \li GraphicsSceneMove + \li Delivered to the widget after its local position has changed. - \row \o GraphicsSceneResize - \o Delivered to the widget after its size has changed. - \row \o Show - \o Delivered to the widget before it has been shown. - \row \o Hide - \o Delivered to the widget after it has been hidden. - \row \o PaletteChange - \o Delivered to the widget after its palette has changed. - \row \o FontChange - \o Delivered to the widget after its font has changed. - \row \o EnabledChange - \o Delivered to the widget after its enabled state has + \row \li GraphicsSceneResize + \li Delivered to the widget after its size has changed. + \row \li Show + \li Delivered to the widget before it has been shown. + \row \li Hide + \li Delivered to the widget after it has been hidden. + \row \li PaletteChange + \li Delivered to the widget after its palette has changed. + \row \li FontChange + \li Delivered to the widget after its font has changed. + \row \li EnabledChange + \li Delivered to the widget after its enabled state has changed. - \row \o StyleChange - \o Delivered to the widget after its style has changed. - \row \o LayoutDirectionChange - \o Delivered to the widget after its layout direction has + \row \li StyleChange + \li Delivered to the widget after its style has changed. + \row \li LayoutDirectionChange + \li Delivered to the widget after its layout direction has changed. - \row \o ContentsRectChange - \o Delivered to the widget after its contents margins/ + \row \li ContentsRectChange + \li Delivered to the widget after its contents margins/ contents rect has changed. \endtable */ diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index ff3de308e5..8530e2c23e 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -251,34 +251,34 @@ void QAbstractItemViewPrivate::_q_scrollerStateChanged() \table \header - \o Keys - \o Functionality + \li Keys + \li Functionality \row - \o Arrow keys - \o Changes the current item and selects it. + \li Arrow keys + \li Changes the current item and selects it. \row - \o Ctrl+Arrow keys - \o Changes the current item but does not select it. + \li Ctrl+Arrow keys + \li Changes the current item but does not select it. \row - \o Shift+Arrow keys - \o Changes the current item and selects it. The previously + \li Shift+Arrow keys + \li Changes the current item and selects it. The previously selected item(s) is not deselected. \row - \o Ctr+Space - \o Toggles selection of the current item. + \li Ctr+Space + \li Toggles selection of the current item. \row - \o Tab/Backtab - \o Changes the current item to the next/previous item. + \li Tab/Backtab + \li Changes the current item to the next/previous item. \row - \o Home/End - \o Selects the first/last item in the model. + \li Home/End + \li Selects the first/last item in the model. \row - \o Page up/Page down - \o Scrolls the rows shown up/down by the number of + \li Page up/Page down + \li Scrolls the rows shown up/down by the number of visible rows in the view. \row - \o Ctrl+A - \o Selects all items in the model. + \li Ctrl+A + \li Selects all items in the model. \endtable Note that the above table assumes that the @@ -1428,7 +1428,7 @@ bool QAbstractItemView::dragEnabled() const \value DragOnly The view supports dragging of its own items \value DropOnly The view accepts drops \value DragDrop The view supports both dragging and dropping - \value InternalMove The view accepts move (\bold{not copy}) operations only + \value InternalMove The view accepts move (\b{not copy}) operations only from itself. Note that the model used needs to provide support for drag and drop operations. diff --git a/src/widgets/itemviews/qdatawidgetmapper.cpp b/src/widgets/itemviews/qdatawidgetmapper.cpp index e4eca4287b..2f7b1f7ecb 100644 --- a/src/widgets/itemviews/qdatawidgetmapper.cpp +++ b/src/widgets/itemviews/qdatawidgetmapper.cpp @@ -279,11 +279,11 @@ void QDataWidgetMapperPrivate::_q_modelDestroyed() Let us assume that we have an item model named \c{model} with the following contents: \table - \row \o 1 \o Qt Norway \o Oslo - \row \o 2 \o Qt Australia \o Brisbane - \row \o 3 \o Qt USA \o Palo Alto - \row \o 4 \o Qt China \o Beijing - \row \o 5 \o Qt Germany \o Berlin + \row \li 1 \li Qt Norway \li Oslo + \row \li 2 \li Qt Australia \li Brisbane + \row \li 3 \li Qt USA \li Palo Alto + \row \li 4 \li Qt China \li Beijing + \row \li 5 \li Qt Germany \li Berlin \endtable The following code will map the columns of the model to widgets called \c mySpinBox, @@ -478,11 +478,11 @@ QModelIndex QDataWidgetMapper::rootIndex() const \snippet doc/src/snippets/code/src_gui_itemviews_qdatawidgetmapper.cpp 1 - \bold{Notes:} + \b{Notes:} \list - \o If the \a widget is already mapped to a section, the + \li If the \a widget is already mapped to a section, the old mapping will be replaced by the new one. - \o Only one-to-one mappings between sections and widgets are allowed. + \li Only one-to-one mappings between sections and widgets are allowed. It is not possible to map a single section to multiple widgets, or to map a single widget to multiple sections. \endlist @@ -781,11 +781,11 @@ void QDataWidgetMapper::clearMapping() Use Qt::Horizontal for tabular data that looks like this: \table - \row \o 1 \o Qt Norway \o Oslo - \row \o 2 \o Qt Australia \o Brisbane - \row \o 3 \o Qt USA \o Silicon Valley - \row \o 4 \o Qt China \o Beijing - \row \o 5 \o Qt Germany \o Berlin + \row \li 1 \li Qt Norway \li Oslo + \row \li 2 \li Qt Australia \li Brisbane + \row \li 3 \li Qt USA \li Silicon Valley + \row \li 4 \li Qt China \li Beijing + \row \li 5 \li Qt Germany \li Berlin \endtable If the orientation is set to Qt::Vertical, a widget is mapped to @@ -796,9 +796,9 @@ void QDataWidgetMapper::clearMapping() Use Qt::Vertical for tabular data that looks like this: \table - \row \o 1 \o 2 \o 3 \o 4 \o 5 - \row \o Qt Norway \o Qt Australia \o Qt USA \o Qt China \o Qt Germany - \row \o Oslo \o Brisbane \o Silicon Valley \o Beijing \i Berlin + \row \li 1 \li 2 \li 3 \li 4 \li 5 + \row \li Qt Norway \li Qt Australia \li Qt USA \li Qt China \li Qt Germany + \row \li Oslo \li Brisbane \li Silicon Valley \li Beijing \li Berlin \endtable Changing the orientation clears all existing mappings. diff --git a/src/widgets/itemviews/qdirmodel.cpp b/src/widgets/itemviews/qdirmodel.cpp index ee097e5c41..490c272e39 100644 --- a/src/widgets/itemviews/qdirmodel.cpp +++ b/src/widgets/itemviews/qdirmodel.cpp @@ -1011,12 +1011,12 @@ QModelIndex QDirModel::mkdir(const QModelIndex &parent, const QString &name) /*! Removes the directory corresponding to the model item \a index in the - directory model and \bold{deletes the corresponding directory from the + directory model and \b{deletes the corresponding directory from the file system}, returning true if successful. If the directory cannot be removed, false is returned. \warning This function deletes directories from the file system; it does - \bold{not} move them to a location where they can be recovered. + \b{not} move them to a location where they can be recovered. \sa remove() */ @@ -1046,11 +1046,11 @@ bool QDirModel::rmdir(const QModelIndex &index) } /*! - Removes the model item \a index from the directory model and \bold{deletes the + Removes the model item \a index from the directory model and \b{deletes the corresponding file from the file system}, returning true if successful. If the item cannot be removed, false is returned. - \warning This function deletes files from the file system; it does \bold{not} + \warning This function deletes files from the file system; it does \b{not} move them to a location where they can be recovered. \sa rmdir() @@ -1134,7 +1134,7 @@ QIcon QDirModel::fileIcon(const QModelIndex &index) const /*! Returns the file information for the specified model \a index. - \bold{Note:} If the model index represents a symbolic link in the + \b{Note:} If the model index represents a symbolic link in the underlying filing system, the file information returned will contain information about the symbolic link itself, regardless of whether resolveSymlinks is enabled or not. diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp index feec3fcbc5..419c62ff65 100644 --- a/src/widgets/itemviews/qitemdelegate.cpp +++ b/src/widgets/itemviews/qitemdelegate.cpp @@ -231,12 +231,12 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const reimplemented here: \list - \o createEditor() returns the widget used to change data from the model + \li createEditor() returns the widget used to change data from the model and can be reimplemented to customize editing behavior. - \o setEditorData() provides the widget with data to manipulate. - \o updateEditorGeometry() ensures that the editor is displayed correctly + \li setEditorData() provides the widget with data to manipulate. + \li updateEditorGeometry() ensures that the editor is displayed correctly with respect to the item view. - \o setModelData() returns updated data to the model. + \li setModelData() returns updated data to the model. \endlist The closeEditor() signal indicates that the user has completed editing the data, @@ -250,28 +250,28 @@ QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const appearance of the delegate as described in the following table. \table - \header \o Role \o Accepted Types + \header \li Role \li Accepted Types \omit - \row \o \l Qt::AccessibleDescriptionRole \o QString - \row \o \l Qt::AccessibleTextRole \o QString + \row \li \l Qt::AccessibleDescriptionRole \li QString + \row \li \l Qt::AccessibleTextRole \li QString \endomit - \row \o \l Qt::BackgroundRole \o QBrush - \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead) - \row \o \l Qt::CheckStateRole \o Qt::CheckState - \row \o \l Qt::DecorationRole \o QIcon, QPixmap and QColor - \row \o \l Qt::DisplayRole \o QString and types with a string representation - \row \o \l Qt::EditRole \o See QItemEditorFactory for details - \row \o \l Qt::FontRole \o QFont - \row \o \l Qt::SizeHintRole \o QSize + \row \li \l Qt::BackgroundRole \li QBrush + \row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead) + \row \li \l Qt::CheckStateRole \li Qt::CheckState + \row \li \l Qt::DecorationRole \li QIcon, QPixmap and QColor + \row \li \l Qt::DisplayRole \li QString and types with a string representation + \row \li \l Qt::EditRole \li See QItemEditorFactory for details + \row \li \l Qt::FontRole \li QFont + \row \li \l Qt::SizeHintRole \li QSize \omit - \row \o \l Qt::StatusTipRole \o + \row \li \l Qt::StatusTipRole \li \endomit - \row \o \l Qt::TextAlignmentRole \o Qt::Alignment - \row \o \l Qt::ForegroundRole \o QBrush - \row \o \l Qt::TextColorRole \o QColor (obsolete; use Qt::ForegroundRole instead) + \row \li \l Qt::TextAlignmentRole \li Qt::Alignment + \row \li \l Qt::ForegroundRole \li QBrush + \row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead) \omit - \row \o \l Qt::ToolTipRole - \row \o \l Qt::WhatsThisRole + \row \li \l Qt::ToolTipRole + \row \li \l Qt::WhatsThisRole \endomit \endtable @@ -1152,11 +1152,11 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect, key press events are handled by default: \list - \o \gui Tab - \o \gui Backtab - \o \gui Enter - \o \gui Return - \o \gui Esc + \li \gui Tab + \li \gui Backtab + \li \gui Enter + \li \gui Return + \li \gui Esc \endlist In the case of \gui Tab, \gui Backtab, \gui Enter and \gui Return diff --git a/src/widgets/itemviews/qitemeditorfactory.cpp b/src/widgets/itemviews/qitemeditorfactory.cpp index 468929a554..b4180c18dd 100644 --- a/src/widgets/itemviews/qitemeditorfactory.cpp +++ b/src/widgets/itemviews/qitemeditorfactory.cpp @@ -102,16 +102,16 @@ public: types and the standard editors provided. \table - \header \o Type \o Editor Widget - \row \o bool \o QComboBox - \row \o double \o QDoubleSpinBox - \row \o int \o{1,2} QSpinBox - \row \o unsigned int - \row \o QDate \o QDateEdit - \row \o QDateTime \o QDateTimeEdit - \row \o QPixmap \o QLabel - \row \o QString \o QLineEdit - \row \o QTime \o QTimeEdit + \header \li Type \li Editor Widget + \row \li bool \li QComboBox + \row \li double \li QDoubleSpinBox + \row \li int \li{1,2} QSpinBox + \row \li unsigned int + \row \li QDate \li QDateEdit + \row \li QDateTime \li QDateTimeEdit + \row \li QPixmap \li QLabel + \row \li QString \li QLineEdit + \row \li QTime \li QTimeEdit \endtable Additional editors can be registered with the registerEditor() function. @@ -168,7 +168,7 @@ QItemEditorFactory::~QItemEditorFactory() /*! Registers an item editor creator specified by \a creator for the given \a userType of data. - \bold{Note:} The factory takes ownership of the item editor creator and will destroy + \b{Note:} The factory takes ownership of the item editor creator and will destroy it if a new creator for the same type is registered later. \sa createEditor() diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp index 8d069a8c7e..b00b1073a3 100644 --- a/src/widgets/itemviews/qlistview.cpp +++ b/src/widgets/itemviews/qlistview.cpp @@ -108,12 +108,12 @@ QT_BEGIN_NAMESPACE be rendered as large or small icons depending on their iconSize(). \table 100% - \row \o \inlineimage windowsxp-listview.png Screenshot of a Windows XP style list view - \o \inlineimage macintosh-listview.png Screenshot of a Macintosh style table view - \o \inlineimage plastique-listview.png Screenshot of a Plastique style table view - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} list view. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} list view. - \o A \l{Plastique Style Widget Gallery}{Plastique style} list view. + \row \li \inlineimage windowsxp-listview.png Screenshot of a Windows XP style list view + \li \inlineimage macintosh-listview.png Screenshot of a Macintosh style table view + \li \inlineimage plastique-listview.png Screenshot of a Plastique style table view + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} list view. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} list view. + \li A \l{Plastique Style Widget Gallery}{Plastique style} list view. \endtable \section1 Improving Performance diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index bb39546ec8..01cb7b4235 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -1187,12 +1187,12 @@ void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, new current item and the item that was previously current. \table 100% - \row \o \inlineimage windowsxp-listview.png Screenshot of a Windows XP style list widget - \o \inlineimage macintosh-listview.png Screenshot of a Macintosh style table widget - \o \inlineimage plastique-listview.png Screenshot of a Plastique style table widget - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} list widget. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} list widget. - \o A \l{Plastique Style Widget Gallery}{Plastique style} list widget. + \row \li \inlineimage windowsxp-listview.png Screenshot of a Windows XP style list widget + \li \inlineimage macintosh-listview.png Screenshot of a Macintosh style table widget + \li \inlineimage plastique-listview.png Screenshot of a Plastique style table widget + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} list widget. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} list widget. + \li A \l{Plastique Style Widget Gallery}{Plastique style} list widget. \endtable \sa QListWidgetItem, QListView, QTreeView, {Model/View Programming}, diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp index d54d78512a..93893afaa8 100644 --- a/src/widgets/itemviews/qstyleditemdelegate.cpp +++ b/src/widgets/itemviews/qstyleditemdelegate.cpp @@ -143,28 +143,28 @@ public: each of the roles to determine the appearance of items in views. \table - \header \o Role \o Accepted Types + \header \li Role \li Accepted Types \omit - \row \o \l Qt::AccessibleDescriptionRole \o QString - \row \o \l Qt::AccessibleTextRole \o QString + \row \li \l Qt::AccessibleDescriptionRole \li QString + \row \li \l Qt::AccessibleTextRole \li QString \endomit - \row \o \l Qt::BackgroundRole \o QBrush - \row \o \l Qt::BackgroundColorRole \o QColor (obsolete; use Qt::BackgroundRole instead) - \row \o \l Qt::CheckStateRole \o Qt::CheckState - \row \o \l Qt::DecorationRole \o QIcon, QPixmap, QImage and QColor - \row \o \l Qt::DisplayRole \o QString and types with a string representation - \row \o \l Qt::EditRole \o See QItemEditorFactory for details - \row \o \l Qt::FontRole \o QFont - \row \o \l Qt::SizeHintRole \o QSize + \row \li \l Qt::BackgroundRole \li QBrush + \row \li \l Qt::BackgroundColorRole \li QColor (obsolete; use Qt::BackgroundRole instead) + \row \li \l Qt::CheckStateRole \li Qt::CheckState + \row \li \l Qt::DecorationRole \li QIcon, QPixmap, QImage and QColor + \row \li \l Qt::DisplayRole \li QString and types with a string representation + \row \li \l Qt::EditRole \li See QItemEditorFactory for details + \row \li \l Qt::FontRole \li QFont + \row \li \l Qt::SizeHintRole \li QSize \omit - \row \o \l Qt::StatusTipRole \o + \row \li \l Qt::StatusTipRole \li \endomit - \row \o \l Qt::TextAlignmentRole \o Qt::Alignment - \row \o \l Qt::ForegroundRole \o QBrush - \row \o \l Qt::TextColorRole \o QColor (obsolete; use Qt::ForegroundRole instead) + \row \li \l Qt::TextAlignmentRole \li Qt::Alignment + \row \li \l Qt::ForegroundRole \li QBrush + \row \li \l Qt::TextColorRole \li QColor (obsolete; use Qt::ForegroundRole instead) \omit - \row \o \l Qt::ToolTipRole - \row \o \l Qt::WhatsThisRole + \row \li \l Qt::ToolTipRole + \row \li \l Qt::WhatsThisRole \endomit \endtable @@ -211,12 +211,12 @@ public: following virtual functions must be reimplemented: \list - \o createEditor() returns the widget used to change data from the model + \li createEditor() returns the widget used to change data from the model and can be reimplemented to customize editing behavior. - \o setEditorData() provides the widget with data to manipulate. - \o updateEditorGeometry() ensures that the editor is displayed correctly + \li setEditorData() provides the widget with data to manipulate. + \li updateEditorGeometry() ensures that the editor is displayed correctly with respect to the item view. - \o setModelData() returns updated data to the model. + \li setModelData() returns updated data to the model. \endlist The \l{Star Delegate Example}{Star Delegate} example creates @@ -618,11 +618,11 @@ void QStyledItemDelegate::setItemEditorFactory(QItemEditorFactory *factory) key press events are handled by default: \list - \o \gui Tab - \o \gui Backtab - \o \gui Enter - \o \gui Return - \o \gui Esc + \li \gui Tab + \li \gui Backtab + \li \gui Enter + \li \gui Return + \li \gui Esc \endlist In the case of \gui Tab, \gui Backtab, \gui Enter and \gui Return diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 7e6420bb53..d3bc826750 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -980,8 +980,8 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 later retrieved with \l{QAbstractItemView::}{indexWidget()}. \table - \row \o \inlineimage qtableview-resized.png - \o By default, the cells in a table do not expand to fill the available space. + \row \li \inlineimage qtableview-resized.png + \li By default, the cells in a table do not expand to fill the available space. You can make the cells fill the available space by stretching the last header section. Access the relevant header using horizontalHeader() @@ -1010,12 +1010,12 @@ void QTableViewPrivate::drawCell(QPainter *painter, const QStyleOptionViewItemV4 its appearance in other styles. \table 100% - \row \o \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table view - \o \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table view - \o \inlineimage plastique-tableview.png Screenshot of a Plastique style table view - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} table view. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} table view. - \o A \l{Plastique Style Widget Gallery}{Plastique style} table view. + \row \li \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table view + \li \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table view + \li \inlineimage plastique-tableview.png Screenshot of a Plastique style table view + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} table view. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} table view. + \li A \l{Plastique Style Widget Gallery}{Plastique style} table view. \endtable \sa QTableWidget, {View Classes}, QAbstractItemModel, QAbstractItemView, diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 5932f20327..7ae74640d6 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -1537,12 +1537,12 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other) clear() function. \table 100% - \row \o \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table widget - \o \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table widget - \o \inlineimage plastique-tableview.png Screenshot of a Plastique style table widget - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} table widget. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} table widget. - \o A \l{Plastique Style Widget Gallery}{Plastique style} table widget. + \row \li \inlineimage windowsxp-tableview.png Screenshot of a Windows XP style table widget + \li \inlineimage macintosh-tableview.png Screenshot of a Macintosh style table widget + \li \inlineimage plastique-tableview.png Screenshot of a Plastique style table widget + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} table widget. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} table widget. + \li A \l{Plastique Style Widget Gallery}{Plastique style} table widget. \endtable \sa QTableWidgetItem, QTableView, {Model/View Programming} diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 7f5e5964ab..c54c11d0f5 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -113,29 +113,29 @@ QT_BEGIN_NAMESPACE navigate in the view and interact with the contents of items: \table - \header \o Key \o Action - \row \o Up \o Moves the cursor to the item in the same column on + \header \li Key \li Action + \row \li Up \li Moves the cursor to the item in the same column on the previous row. If the parent of the current item has no more rows to navigate to, the cursor moves to the relevant item in the last row of the sibling that precedes the parent. - \row \o Down \o Moves the cursor to the item in the same column on + \row \li Down \li Moves the cursor to the item in the same column on the next row. If the parent of the current item has no more rows to navigate to, the cursor moves to the relevant item in the first row of the sibling that follows the parent. - \row \o Left \o Hides the children of the current item (if present) + \row \li Left \li Hides the children of the current item (if present) by collapsing a branch. - \row \o Minus \o Same as LeftArrow. - \row \o Right \o Reveals the children of the current item (if present) + \row \li Minus \li Same as LeftArrow. + \row \li Right \li Reveals the children of the current item (if present) by expanding a branch. - \row \o Plus \o Same as RightArrow. - \row \o Asterisk \o Expands all children of the current item (if present). - \row \o PageUp \o Moves the cursor up one page. - \row \o PageDown \o Moves the cursor down one page. - \row \o Home \o Moves the cursor to an item in the same column of the first + \row \li Plus \li Same as RightArrow. + \row \li Asterisk \li Expands all children of the current item (if present). + \row \li PageUp \li Moves the cursor up one page. + \row \li PageDown \li Moves the cursor down one page. + \row \li Home \li Moves the cursor to an item in the same column of the first row of the first top-level item in the model. - \row \o End \o Moves the cursor to an item in the same column of the last + \row \li End \li Moves the cursor to an item in the same column of the last row of the last top-level item in the model. - \row \o F2 \o In editable models, this opens the current item for editing. + \row \li F2 \li In editable models, this opens the current item for editing. The Escape key can be used to cancel the editing process and revert any changes to the data displayed. \endtable @@ -145,12 +145,12 @@ QT_BEGIN_NAMESPACE \endomit \table 100% - \row \o \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree view - \o \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree view - \o \inlineimage plastique-treeview.png Screenshot of a Plastique style tree view - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} tree view. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} tree view. - \o A \l{Plastique Style Widget Gallery}{Plastique style} tree view. + \row \li \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree view + \li \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree view + \li \inlineimage plastique-treeview.png Screenshot of a Plastique style tree view + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} tree view. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} tree view. + \li A \l{Plastique Style Widget Gallery}{Plastique style} tree view. \endtable \section1 Improving Performance @@ -3146,7 +3146,7 @@ void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, i } /** \internal - creates and initialize the viewItem structure of the children of the element \i + creates and initialize the viewItem structure of the children of the element \li set \a recursiveExpanding if the function has to expand all the children (called from expandAll) \a afterIsUninitialized is when we recurse from layout(-1), it means all the items after 'i' are diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index cec709a816..156121a533 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -2376,12 +2376,12 @@ void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft, whether sorting is enabled. \table 100% - \row \o \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree widget - \o \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree widget - \o \inlineimage plastique-treeview.png Screenshot of a Plastique style tree widget - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} tree widget. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} tree widget. - \o A \l{Plastique Style Widget Gallery}{Plastique style} tree widget. + \row \li \inlineimage windowsxp-treeview.png Screenshot of a Windows XP style tree widget + \li \inlineimage macintosh-treeview.png Screenshot of a Macintosh style tree widget + \li \inlineimage plastique-treeview.png Screenshot of a Plastique style tree widget + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} tree widget. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} tree widget. + \li A \l{Plastique Style Widget Gallery}{Plastique style} tree widget. \endtable \sa QTreeWidgetItem, QTreeWidgetItemIterator, QTreeView, @@ -3263,7 +3263,7 @@ void QTreeWidget::collapseItem(const QTreeWidgetItem *item) /*! Clears the tree widget by removing all of its items and selections. - \bold{Note:} Since each item is removed from the tree widget before being + \b{Note:} Since each item is removed from the tree widget before being deleted, the return value of QTreeWidgetItem::treeWidget() will be invalid when called from an item's destructor. diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index c350223278..095b58eeaf 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -185,7 +185,7 @@ QApplicationPrivate::~QApplicationPrivate() for QWidget-based applications. It handles widget specific initialization, finalization, and provides session management. - For any GUI application using Qt, there is precisely \bold one QApplication + For any GUI application using Qt, there is precisely \b one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time. For non-QWidget based Qt applications, use QGuiApplication instead, as it does not depend on the \l QtWidgets library. @@ -195,41 +195,41 @@ QApplicationPrivate::~QApplicationPrivate() QApplication's main areas of responsibility are: \list - \o It initializes the application with the user's desktop settings + \li It initializes the application with the user's desktop settings such as palette(), font() and doubleClickInterval(). It keeps track of these properties in case the user changes the desktop globally, for example through some kind of control panel. - \o It performs event handling, meaning that it receives events + \li It performs event handling, meaning that it receives events from the underlying window system and dispatches them to the relevant widgets. By using sendEvent() and postEvent() you can send your own events to widgets. - \o It parses common command line arguments and sets its internal + \li It parses common command line arguments and sets its internal state accordingly. See the \l{QApplication::QApplication()} {constructor documentation} below for more details. - \o It defines the application's look and feel, which is + \li It defines the application's look and feel, which is encapsulated in a QStyle object. This can be changed at runtime with setStyle(). - \o It specifies how the application is to allocate colors. See + \li It specifies how the application is to allocate colors. See setColorSpec() for details. - \o It provides localization of strings that are visible to the + \li It provides localization of strings that are visible to the user via translate(). - \o It provides some magical objects like the desktop() and the + \li It provides some magical objects like the desktop() and the clipboard(). - \o It knows about the application's windows. You can ask which + \li It knows about the application's windows. You can ask which widget is at a certain position using widgetAt(), get a list of topLevelWidgets() and closeAllWindows(), etc. - \o It manages the application's mouse cursor handling, see + \li It manages the application's mouse cursor handling, see setOverrideCursor() - \o It provides support for sophisticated \l{Session Management} + \li It provides support for sophisticated \l{Session Management} {session management}. This makes it possible for applications to terminate gracefully when the user logs out, to cancel a shutdown process if termination isn't possible and even to @@ -246,11 +246,11 @@ QApplicationPrivate::~QApplicationPrivate() \table \header - \o{2,1} Groups of functions + \li{2,1} Groups of functions \row - \o System settings - \o desktopSettingsAware(), + \li System settings + \li desktopSettingsAware(), setDesktopSettingsAware(), cursorFlashTime(), setCursorFlashTime(), @@ -266,8 +266,8 @@ QApplicationPrivate::~QApplicationPrivate() fontMetrics(). \row - \o Event handling - \o exec(), + \li Event handling + \li exec(), processEvents(), exit(), quit(). @@ -279,24 +279,24 @@ QApplicationPrivate::~QApplicationPrivate() notify(). \row - \o GUI Styles - \o style(), + \li GUI Styles + \li style(), setStyle(). \row - \o Color usage - \o colorSpec(), + \li Color usage + \li colorSpec(), setColorSpec(). \row - \o Text handling - \o installTranslator(), + \li Text handling + \li installTranslator(), removeTranslator() translate(). \row - \o Widgets - \o allWidgets(), + \li Widgets + \li allWidgets(), topLevelWidgets(), desktop(), activePopupWidget(), @@ -307,21 +307,21 @@ QApplicationPrivate::~QApplicationPrivate() widgetAt(). \row - \o Advanced cursor handling - \o overrideCursor(), + \li Advanced cursor handling + \li overrideCursor(), setOverrideCursor(), restoreOverrideCursor(). \row - \o Session management - \o isSessionRestored(), + \li Session management + \li isSessionRestored(), sessionId(), commitData(), saveState(). \row - \o Miscellaneous - \o closeAllWindows(), + \li Miscellaneous + \li closeAllWindows(), startingUp(), closingDown(), type(). @@ -534,25 +534,25 @@ void QApplicationPrivate::process_cmdline() All Qt programs automatically support the following command line options: \list - \o -style= \e style, sets the application GUI style. Possible values + \li -style= \e style, sets the application GUI style. Possible values are \c motif, \c windows, and \c platinum. If you compiled Qt with additional styles or have additional styles as plugins these will be available to the \c -style command line option. - \o -style \e style, is the same as listed above. - \o -stylesheet= \e stylesheet, sets the application \l styleSheet. The + \li -style \e style, is the same as listed above. + \li -stylesheet= \e stylesheet, sets the application \l styleSheet. The value must be a path to a file that contains the Style Sheet. \note Relative URLs in the Style Sheet file are relative to the Style Sheet file's path. - \o -stylesheet \e stylesheet, is the same as listed above. - \o -session= \e session, restores the application from an earlier + \li -stylesheet \e stylesheet, is the same as listed above. + \li -session= \e session, restores the application from an earlier \l{Session Management}{session}. - \o -session \e session, is the same as listed above. - \o -widgetcount, prints debug message at the end about number of + \li -session \e session, is the same as listed above. + \li -widgetcount, prints debug message at the end about number of widgets left undestroyed and maximum number of widgets existed at the same time - \o -reverse, sets the application's layout direction to + \li -reverse, sets the application's layout direction to Qt::RightToLeft - \o -qmljsdebugger=, activates the QML/JS debugger with a specified port. + \li -qmljsdebugger=, activates the QML/JS debugger with a specified port. The value must be of format port:1234[,block], where block is optional and will make the application wait until a debugger connects to it. \endlist @@ -968,7 +968,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis \since 4.4 \brief defines a threshold for auto maximizing widgets - \bold{The auto maximize threshold is only available as part of Qt for + \b{The auto maximize threshold is only available as part of Qt for Windows CE.} This property defines a threshold for the size of a window as a percentage @@ -997,7 +997,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis the WA_InputMethodEnabled attribute set, and is typically used to launch a virtual keyboard on devices which have very few or no keys. - \bold{ The property only has an effect on platforms which use software input + \b{ The property only has an effect on platforms which use software input panels, such as Windows CE.} The default is platform dependent. @@ -1275,21 +1275,21 @@ int QApplication::colorSpec() The options are: \list - \o QApplication::NormalColor. This is the default color allocation + \li QApplication::NormalColor. This is the default color allocation strategy. Use this option if your application uses buttons, menus, texts and pixmaps with few colors. With this option, the application uses system global colors. This works fine for most applications under X11, but on the Windows platform, it may cause dithering of non-standard colors. - \o QApplication::CustomColor. Use this option if your application + \li QApplication::CustomColor. Use this option if your application needs a small number of custom colors. On X11, this option is the same as NormalColor. On Windows, Qt creates a Windows palette, and allocates colors to it on demand. - \o QApplication::ManyColor. Use this option if your application is + \li QApplication::ManyColor. Use this option if your application is very color hungry, e.g., it requires thousands of colors. \br Under X11 the effect is: \list - \o For 256-color displays which have at best a 256 color true + \li For 256-color displays which have at best a 256 color true color visual, the default visual is used, and colors are allocated from a color cube. The color cube is the 6x6x6 (216 color) "Web palette" (the red, green, and blue @@ -1298,7 +1298,7 @@ int QApplication::colorSpec() can be changed by the \e -ncols option. The user can force the application to use the true color visual with the \l{QApplication::QApplication()}{-visual} option. - \o For 256-color displays which have a true color visual with + \li For 256-color displays which have a true color visual with more than 256 colors, use that visual. Silicon Graphics X servers this feature, for example. They provide an 8 bit visual by default but can deliver true color when asked. diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp index 4b7153715d..7ea77d211c 100644 --- a/src/widgets/kernel/qboxlayout.cpp +++ b/src/widgets/kernel/qboxlayout.cpp @@ -487,17 +487,17 @@ void QBoxLayoutPrivate::calcHfw(int w) one of four functions: \list - \o addWidget() to add a widget to the QBoxLayout and set the + \li addWidget() to add a widget to the QBoxLayout and set the widget's stretch factor. (The stretch factor is along the row of boxes.) - \o addSpacing() to create an empty box; this is one of the + \li addSpacing() to create an empty box; this is one of the functions you use to create nice and spacious dialogs. See below for ways to set margins. - \o addStretch() to create an empty, stretchable box. + \li addStretch() to create an empty, stretchable box. - \o addLayout() to add a box containing another QLayout to the row + \li addLayout() to add a box containing another QLayout to the row and set that layout's stretch factor. \endlist @@ -508,10 +508,10 @@ void QBoxLayoutPrivate::calcHfw(int w) QBoxLayout also includes two margin widths: \list - \o setContentsMargins() sets the width of the outer border on + \li setContentsMargins() sets the width of the outer border on each side of the widget. This is the width of the reserved space along each of the QBoxLayout's four sides. - \o setSpacing() sets the width between neighboring boxes. (You + \li setSpacing() sets the width between neighboring boxes. (You can use addSpacing() to get more space at a particular spot.) \endlist diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index dd61528124..440f3f1dc2 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -1019,20 +1019,20 @@ QStyle* QFormLayoutPrivate::getStyle() const provides the following advantages: \list - \o \bold{Adherence to the different platform's look and feel guidelines.} + \li \b{Adherence to the different platform's look and feel guidelines.} For example, the \l{Mac OS X Aqua} and KDE guidelines specify that the labels should be right-aligned, whereas Windows and GNOME applications normally use left-alignment. - \o \bold{Support for wrapping long rows.} + \li \b{Support for wrapping long rows.} For devices with small displays, QFormLayout can be set to \l{WrapLongRows}{wrap long rows}, or even to \l{WrapAllRows}{wrap all rows}. - \o \bold{Convenient API for creating label--field pairs.} + \li \b{Convenient API for creating label--field pairs.} The addRow() overload that takes a QString and a QWidget * creates a QLabel behind the scenes and automatically set up @@ -1049,30 +1049,30 @@ QStyle* QFormLayoutPrivate::getStyle() const \table \header - \o QCommonStyle derived styles (except QPlastiqueStyle) - \o QMacStyle - \o QPlastiqueStyle - \o Qt Extended styles + \li QCommonStyle derived styles (except QPlastiqueStyle) + \li QMacStyle + \li QPlastiqueStyle + \li Qt Extended styles \row - \o \inlineimage qformlayout-win.png - \o \inlineimage qformlayout-mac.png - \o \inlineimage qformlayout-kde.png - \o \inlineimage qformlayout-qpe.png + \li \inlineimage qformlayout-win.png + \li \inlineimage qformlayout-mac.png + \li \inlineimage qformlayout-kde.png + \li \inlineimage qformlayout-qpe.png \row - \o Traditional style used for Windows, GNOME, and earlier + \li Traditional style used for Windows, GNOME, and earlier versions of KDE. Labels are left aligned, and expanding fields grow to fill the available space. (This normally corresponds to what we would get using a two-column QGridLayout.) - \o Style based on the + \li Style based on the \l{Mac OS X Aqua} guidelines. Labels are right-aligned, the fields don't grow beyond their size hint, and the form is horizontally centered. - \o Recommended style for + \li Recommended style for \l{KDE applications}. Similar to MacStyle, except that the form is left-aligned and all fields grow to fill the available space. - \o Default style for Qt Extended styles. Labels are right-aligned, + \li Default style for Qt Extended styles. Labels are right-aligned, expanding fields grow to fill the available space, and row wrapping is enabled for long lines. \endtable @@ -1966,7 +1966,7 @@ void QFormLayoutPrivate::arrangeWidgets(const QVector& layouts, Q If the cell is already occupied, the \a widget is not inserted and an error message is sent to the console. - \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setWidget(). + \b{Note:} For most applications, addRow() or insertRow() should be used instead of setWidget(). \sa setLayout() */ @@ -1986,7 +1986,7 @@ void QFormLayout::setWidget(int row, ItemRole role, QWidget *widget) If the cell is already occupied, the \a layout is not inserted and an error message is sent to the console. - \bold{Note:} For most applications, addRow() or insertRow() should be used instead of setLayout(). + \b{Note:} For most applications, addRow() or insertRow() should be used instead of setLayout(). \sa setWidget() */ diff --git a/src/widgets/kernel/qicon.cpp b/src/widgets/kernel/qicon.cpp index eebd57f97e..4f244b1027 100644 --- a/src/widgets/kernel/qicon.cpp +++ b/src/widgets/kernel/qicon.cpp @@ -945,8 +945,8 @@ QString QIcon::themeName() specification can be obtained here: \list - \o \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html} - \o \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html} + \li \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html} + \li \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html} \endlist To fetch an icon from the current icon theme: diff --git a/src/widgets/kernel/qiconengineplugin.cpp b/src/widgets/kernel/qiconengineplugin.cpp index ced4f5dd3e..26c9e7890a 100644 --- a/src/widgets/kernel/qiconengineplugin.cpp +++ b/src/widgets/kernel/qiconengineplugin.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE \ingroup plugins \inmodule QtWidgets - \bold {Use QIconEnginePluginV2 instead.} + \b {Use QIconEnginePluginV2 instead.} The icon engine plugin is a simple plugin interface that makes it easy to create custom icon engines that can be loaded dynamically into applications diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index d5d739e431..541350c35c 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -215,7 +215,7 @@ QSpacerItem *QLayoutPrivate::createSpacerItem(const QLayout *layout, int w, int to a layout, use the addWidget() function; to add a child layout, use the addLayout() function provided by the relevant QLayout subclass. - \bold{Note:} The ownership of \a item is transferred to the layout, and it's + \b{Note:} The ownership of \a item is transferred to the layout, and it's the layout's responsibility to delete it. \sa addWidget(), QBoxLayout::addLayout(), QGridLayout::addLayout() @@ -1270,7 +1270,7 @@ QRect QLayout::alignmentRect(const QRect &r) const is the caller's responsibility to give the widget a reasonable geometry or to put the widget back into a layout. - \bold{Note:} The ownership of \a widget remains the same as + \b{Note:} The ownership of \a widget remains the same as when it was added. \sa removeItem(), QWidget::setGeometry(), addWidget() diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp index 664334d725..814b807b82 100644 --- a/src/widgets/kernel/qlayoutitem.cpp +++ b/src/widgets/kernel/qlayoutitem.cpp @@ -127,15 +127,15 @@ QSizePolicy::operator QVariant() const manipulating empty space in layouts: \table - \header \o Class - \o Functions - \row \o QHBoxLayout - \o \l{QBoxLayout::addSpacing()}{addSpacing()}, + \header \li Class + \li Functions + \row \li QHBoxLayout + \li \l{QBoxLayout::addSpacing()}{addSpacing()}, \l{QBoxLayout::addStretch()}{addStretch()}, \l{QBoxLayout::insertSpacing()}{insertSpacing()}, \l{QBoxLayout::insertStretch()}{insertStretch()} - \row \o QGridLayout - \o \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()}, + \row \li QGridLayout + \li \l{QGridLayout::setRowMinimumHeight()}{setRowMinimumHeight()}, \l{QGridLayout::setRowStretch()}{setRowStretch()}, \l{QGridLayout::setColumnMinimumWidth()}{setColumnMinimumWidth()}, \l{QGridLayout::setColumnStretch()}{setColumnStretch()} @@ -156,16 +156,16 @@ QSizePolicy::operator QVariant() const manipulating widgets in layouts: \table - \header \o Class - \o Functions - \row \o QBoxLayout - \o \l{QBoxLayout::addWidget()}{addWidget()}, + \header \li Class + \li Functions + \row \li QBoxLayout + \li \l{QBoxLayout::addWidget()}{addWidget()}, \l{QBoxLayout::insertWidget()}{insertWidget()}, \l{QBoxLayout::setStretchFactor()}{setStretchFactor()} - \row \o QGridLayout - \o \l{QGridLayout::addWidget()}{addWidget()} - \row \o QStackedLayout - \o \l{QStackedLayout::addWidget()}{addWidget()}, + \row \li QGridLayout + \li \l{QGridLayout::addWidget()}{addWidget()} + \row \li QStackedLayout + \li \l{QStackedLayout::addWidget()}{addWidget()}, \l{QStackedLayout::insertWidget()}{insertWidget()}, \l{QStackedLayout::currentWidget()}{currentWidget()}, \l{QStackedLayout::setCurrentWidget()}{setCurrentWidget()}, @@ -191,7 +191,7 @@ QSizePolicy::operator QVariant() const /*! Sets the alignment of this item to \a alignment. - \bold{Note:} Item alignment is only supported by QLayoutItem subclasses + \b{Note:} Item alignment is only supported by QLayoutItem subclasses where it would have a visual effect. Except for QSpacerItem, which provides blank space for layouts, all public Qt classes that inherit QLayoutItem support item alignment. diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 44995f0959..5eee5752cc 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -484,11 +484,11 @@ void QWidget::setAutoFillBackground(bool enabled) Every widget's constructor accepts one or two standard arguments: \list 1 - \i \c{QWidget *parent = 0} is the parent of the new widget. If it is 0 + \li \c{QWidget *parent = 0} is the parent of the new widget. If it is 0 (the default), the new widget will be a window. If not, it will be a child of \e parent, and be constrained by \e parent's geometry (unless you specify Qt::Window as window flag). - \i \c{Qt::WindowFlags f = 0} (where available) sets the window flags; + \li \c{Qt::WindowFlags f = 0} (where available) sets the window flags; the default is suitable for almost all widgets, but to get, for example, a window without a window system frame, you must use special flags. @@ -593,16 +593,16 @@ void QWidget::setAutoFillBackground(bool enabled) starting with the most common ones: \list - \i paintEvent() is called whenever the widget needs to be repainted. + \li paintEvent() is called whenever the widget needs to be repainted. Every widget displaying custom content must implement it. Painting using a QPainter can only take place in a paintEvent() or a function called by a paintEvent(). - \i resizeEvent() is called when the widget has been resized. - \i mousePressEvent() is called when a mouse button is pressed while + \li resizeEvent() is called when the widget has been resized. + \li mousePressEvent() is called when a mouse button is pressed while the mouse cursor is inside the widget, or when the widget has grabbed the mouse using grabMouse(). Pressing the mouse without releasing it is effectively the same as calling grabMouse(). - \i mouseReleaseEvent() is called when a mouse button is released. A + \li mouseReleaseEvent() is called when a mouse button is released. A widget receives mouse release events when it has received the corresponding mouse press event. This means that if the user presses the mouse inside \e your widget, then drags the mouse @@ -610,7 +610,7 @@ void QWidget::setAutoFillBackground(bool enabled) receives the release event. There is one exception: if a popup menu appears while the mouse button is held down, this popup immediately steals the mouse events. - \i mouseDoubleClickEvent() is called when the user double-clicks in + \li mouseDoubleClickEvent() is called when the user double-clicks in the widget. If the user double-clicks, the widget receives a mouse press event, a mouse release event and finally this event instead of a second mouse press event. (Some mouse move events may also be @@ -625,46 +625,46 @@ void QWidget::setAutoFillBackground(bool enabled) handlers: \list - \i keyPressEvent() is called whenever a key is pressed, and again when + \li keyPressEvent() is called whenever a key is pressed, and again when a key has been held down long enough for it to auto-repeat. The \key Tab and \key Shift+Tab keys are only passed to the widget if they are not used by the focus-change mechanisms. To force those keys to be processed by your widget, you must reimplement QWidget::event(). - \i focusInEvent() is called when the widget gains keyboard focus + \li focusInEvent() is called when the widget gains keyboard focus (assuming you have called setFocusPolicy()). Well-behaved widgets indicate that they own the keyboard focus in a clear but discreet way. - \i focusOutEvent() is called when the widget loses keyboard focus. + \li focusOutEvent() is called when the widget loses keyboard focus. \endlist You may be required to also reimplement some of the less common event handlers: \list - \i mouseMoveEvent() is called whenever the mouse moves while a mouse + \li mouseMoveEvent() is called whenever the mouse moves while a mouse button is held down. This can be useful during drag and drop operations. If you call \l{setMouseTracking()}{setMouseTracking}(true), you get mouse move events even when no buttons are held down. (See also the \l{Drag and Drop} guide.) - \i keyReleaseEvent() is called whenever a key is released and while it + \li keyReleaseEvent() is called whenever a key is released and while it is held down (if the key is auto-repeating). In that case, the widget will receive a pair of key release and key press event for every repeat. The \key Tab and \key Shift+Tab keys are only passed to the widget if they are not used by the focus-change mechanisms. To force those keys to be processed by your widget, you must reimplement QWidget::event(). - \i wheelEvent() is called whenever the user turns the mouse wheel + \li wheelEvent() is called whenever the user turns the mouse wheel while the widget has the focus. - \i enterEvent() is called when the mouse enters the widget's screen + \li enterEvent() is called when the mouse enters the widget's screen space. (This excludes screen space owned by any of the widget's children.) - \i leaveEvent() is called when the mouse leaves the widget's screen + \li leaveEvent() is called when the mouse leaves the widget's screen space. If the mouse enters a child widget it will not cause a leaveEvent(). - \i moveEvent() is called when the widget has been moved relative to + \li moveEvent() is called when the widget has been moved relative to its parent. - \i closeEvent() is called when the user closes the widget (or when + \li closeEvent() is called when the user closes the widget (or when close() is called). \endlist @@ -682,27 +682,27 @@ void QWidget::setAutoFillBackground(bool enabled) \section1 Groups of Functions and Properties \table - \header \i Context \i Functions and Properties + \header \li Context \li Functions and Properties - \row \i Window functions \i + \row \li Window functions \li show(), hide(), raise(), lower(), close(). - \row \i Top-level windows \i + \row \li Top-level windows \li \l windowModified, \l windowTitle, \l windowIcon, \l windowIconText, \l isActiveWindow, activateWindow(), \l minimized, showMinimized(), \l maximized, showMaximized(), \l fullScreen, showFullScreen(), showNormal(). - \row \i Window contents \i + \row \li Window contents \li update(), repaint(), scroll(). - \row \i Geometry \i + \row \li Geometry \li \l pos, x(), y(), \l rect, \l size, width(), height(), move(), resize(), \l sizePolicy, sizeHint(), minimumSizeHint(), updateGeometry(), layout(), @@ -713,7 +713,7 @@ void QWidget::setAutoFillBackground(bool enabled) \l maximumSize, \l minimumSize, \l sizeIncrement, \l baseSize, setFixedSize() - \row \i Mode \i + \row \li Mode \li \l visible, isVisibleTo(), \l enabled, isEnabledTo(), \l modal, @@ -722,7 +722,7 @@ void QWidget::setAutoFillBackground(bool enabled) \l updatesEnabled, visibleRegion(). - \row \i Look and feel \i + \row \li Look and feel \li style(), setStyle(), \l styleSheet, @@ -732,17 +732,17 @@ void QWidget::setAutoFillBackground(bool enabled) backgroundRole(), setBackgroundRole(), fontInfo(), fontMetrics(). - \row \i Keyboard focus functions \i + \row \li Keyboard focus functions \li \l focus, \l focusPolicy, setFocus(), clearFocus(), setTabOrder(), setFocusProxy(), focusNextChild(), focusPreviousChild(). - \row \i Mouse and keyboard grabbing \i + \row \li Mouse and keyboard grabbing \li grabMouse(), releaseMouse(), grabKeyboard(), releaseKeyboard(), mouseGrabber(), keyboardGrabber(). - \row \i Event handlers \i + \row \li Event handlers \li event(), mousePressEvent(), mouseReleaseEvent(), @@ -769,11 +769,11 @@ void QWidget::setAutoFillBackground(bool enabled) customEvent(). changeEvent(), - \row \i System functions \i + \row \li System functions \li parentWidget(), window(), setParent(), winId(), find(), metric(). - \row \i Interactive help \i + \row \li Interactive help \li setToolTip(), setWhatsThis() \endtable @@ -815,15 +815,15 @@ void QWidget::setAutoFillBackground(bool enabled) achieve different effects: \list - \i The left widget has no additional properties or widget attributes + \li The left widget has no additional properties or widget attributes set. This default state suits most custom widgets using transparency, are irregularly-shaped, or do not paint over their entire area with an opaque brush. - \i The center widget has the \l autoFillBackground property set. This + \li The center widget has the \l autoFillBackground property set. This property is used with custom widgets that rely on the widget to supply a default background, and do not paint over their entire area with an opaque brush. - \i The right widget has the Qt::WA_OpaquePaintEvent widget attribute + \li The right widget has the Qt::WA_OpaquePaintEvent widget attribute set. This indicates that the widget will paint over its entire area with opaque colors. The widget's area will initially be \e{uninitialized}, represented in the diagram with a red diagonal @@ -874,9 +874,9 @@ void QWidget::setAutoFillBackground(bool enabled) Platform notes: \list - \o X11: This feature relies on the use of an X server that supports ARGB visuals + \li X11: This feature relies on the use of an X server that supports ARGB visuals and a compositing window manager. - \o Windows: The widget needs to have the Qt::FramelessWindowHint window flag set + \li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set for the translucency to work. \endlist @@ -891,14 +891,14 @@ void QWidget::setAutoFillBackground(bool enabled) one of the following options: \list 1 - \i Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment. - \i Set the Qt::AA_NativeWindows attribute on your application. All + \li Use the \c{QT_USE_NATIVE_WINDOWS=1} in your environment. + \li Set the Qt::AA_NativeWindows attribute on your application. All widgets will be native widgets. - \i Set the Qt::WA_NativeWindow attribute on widgets: The widget itself + \li Set the Qt::WA_NativeWindow attribute on widgets: The widget itself and all of its ancestors will become native (unless Qt::WA_DontCreateNativeAncestors is set). - \i Call QWidget::winId to enforce a native window (this implies 3). - \i Set the Qt::WA_PaintOnScreen attribute to enforce a native window + \li Call QWidget::winId to enforce a native window (this implies 3). + \li Set the Qt::WA_PaintOnScreen attribute to enforce a native window (this implies 3). \endlist @@ -957,17 +957,17 @@ QRegion qt_dirtyRegion(QWidget *widget) /* Widget state flags: \list - \i Qt::WA_WState_Created The widget has a valid winId(). - \i Qt::WA_WState_Visible The widget is currently visible. - \i Qt::WA_WState_Hidden The widget is hidden, i.e. it won't + \li Qt::WA_WState_Created The widget has a valid winId(). + \li Qt::WA_WState_Visible The widget is currently visible. + \li Qt::WA_WState_Hidden The widget is hidden, i.e. it won't become visible unless you call show() on it. Qt::WA_WState_Hidden implies !Qt::WA_WState_Visible. - \i Qt::WA_WState_CompressKeys Compress keyboard events. - \i Qt::WA_WState_BlockUpdates Repaints and updates are disabled. - \i Qt::WA_WState_InPaintEvent Currently processing a paint event. - \i Qt::WA_WState_Reparented The widget has been reparented. - \i Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending. - \i Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops(). + \li Qt::WA_WState_CompressKeys Compress keyboard events. + \li Qt::WA_WState_BlockUpdates Repaints and updates are disabled. + \li Qt::WA_WState_InPaintEvent Currently processing a paint event. + \li Qt::WA_WState_Reparented The widget has been reparented. + \li Qt::WA_WState_ConfigPending A configuration (resize/move) event is pending. + \li Qt::WA_WState_DND (Deprecated) The widget supports drag and drop, see setAcceptDrops(). \endlist */ @@ -5689,16 +5689,16 @@ QString QWidget::windowIconText() const On Mac OS X: \list - \o The file name of the specified path, obtained using QFileInfo::fileName(). + \li The file name of the specified path, obtained using QFileInfo::fileName(). \endlist On Windows and X11: \list - \o The file name of the specified path, obtained using QFileInfo::fileName(). - \o An optional \c{*} character, if the \l windowModified property is set. - \o The \c{0x2014} unicode character, padded either side by spaces. - \o The application name, obtained from the application's + \li The file name of the specified path, obtained using QFileInfo::fileName(). + \li An optional \c{*} character, if the \l windowModified property is set. + \li The \c{0x2014} unicode character, padded either side by spaces. + \li The application name, obtained from the application's \l{QCoreApplication::}{applicationName} property. \endlist @@ -7164,9 +7164,9 @@ void QWidgetPrivate::hide_helper() Widgets are hidden if: \list - \o they were created as independent windows, - \o they were created as children of visible widgets, - \o hide() or setVisible(false) was called. + \li they were created as independent windows, + \li they were created as children of visible widgets, + \li hide() or setVisible(false) was called. \endlist */ @@ -8587,9 +8587,9 @@ void QWidget::leaveEvent(QEvent *) happen for one of the following reasons: \list - \o repaint() or update() was invoked, - \o the widget was obscured and has now been uncovered, or - \o many other reasons. + \li repaint() or update() was invoked, + \li the widget was obscured and has now been uncovered, or + \li many other reasons. \endlist Many widgets can simply repaint their entire surface when asked to, but @@ -8612,13 +8612,13 @@ void QWidget::leaveEvent(QEvent *) Since Qt 4.0, QWidget automatically double-buffers its painting, so there is no need to write double-buffering code in paintEvent() to avoid flicker. - \bold{Note for the X11 platform}: It is possible to toggle global double + \b{Note for the X11 platform}: It is possible to toggle global double buffering by calling \c qt_x11_set_global_double_buffer(). For example, \snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 14 \note Generally, you should refrain from calling update() or repaint() - \bold{inside} a paintEvent(). For example, calling update() or repaint() on + \b{inside} a paintEvent(). For example, calling update() or repaint() on children inside a paintevent() results in undefined behavior; the child may or may not get a paint event. @@ -8960,8 +8960,8 @@ void QWidget::hideEvent(QHideEvent *) x11Event(), winEvent() and macEvent() of Qt 4. \table - \header \i Platform \i Event Type Identifier \i Message Type \i Result Type - \row \i Windows \i "windows_generic_MSG" \i MSG * \i LRESULT + \header \li Platform \li Event Type Identifier \li Message Type \li Result Type + \row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT \endtable */ @@ -8991,7 +8991,7 @@ bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *resu If you need to change some settings when a widget is polished, reimplement event() and handle the QEvent::Polish event type. - \bold{Note:} The function is declared const so that it can be called from + \b{Note:} The function is declared const so that it can be called from other const functions (e.g., sizeHint()). \sa event() @@ -11081,7 +11081,7 @@ void QWidget::ungrabGesture(Qt::GestureType gesture) \note Only visible widgets can grab mouse input. If isVisible() returns false for a widget, that widget cannot call grabMouse(). - \note \bold{(Mac OS X developers)} For \e Cocoa, calling + \note \b{(Mac OS X developers)} For \e Cocoa, calling grabMouse() on a widget only works when the mouse is inside the frame of that widget. For \e Carbon, it works outside the widget's frame as well, like for Windows and X11. @@ -11101,7 +11101,7 @@ void QWidget::ungrabGesture(Qt::GestureType gesture) \warning Grabbing the mouse might lock the terminal. - \note \bold{(Mac OS X developers)} See the note in QWidget::grabMouse(). + \note \b{(Mac OS X developers)} See the note in QWidget::grabMouse(). \sa releaseMouse(), grabKeyboard(), releaseKeyboard(), setCursor() */ diff --git a/src/widgets/kernel/qwidgetaction.cpp b/src/widgets/kernel/qwidgetaction.cpp index 14369513da..c3fc6c7cfb 100644 --- a/src/widgets/kernel/qwidgetaction.cpp +++ b/src/widgets/kernel/qwidgetaction.cpp @@ -87,17 +87,17 @@ QT_BEGIN_NAMESPACE Note that it is up to the widget to activate the action, for example by reimplementing mouse event handlers and calling QAction::trigger(). - \bold {Mac OS X}: If you add a widget to a menu in the application's menu + \b {Mac OS X}: If you add a widget to a menu in the application's menu bar on Mac OS X, the widget will be added and it will function but with some limitations: \list 1 - \o The widget is reparented away from the QMenu to the native menu + \li The widget is reparented away from the QMenu to the native menu view. If you show the menu in some other place (e.g. as a popup menu), the widget will not be there. - \o Focus/Keyboard handling of the widget is not possible. - \o Due to Apple's design, mouse tracking on the widget currently does + \li Focus/Keyboard handling of the widget is not possible. + \li Due to Apple's design, mouse tracking on the widget currently does not work. - \o Connecting the triggered() signal to a slot that opens a modal + \li Connecting the triggered() signal to a slot that opens a modal dialog will cause a crash in Mac OS X 10.4 (known bug acknowledged by Apple), a workaround is to use a QueuedConnection instead of a DirectConnection. diff --git a/src/widgets/styles/qmacstyle.qdoc b/src/widgets/styles/qmacstyle.qdoc index d48a65c41f..dc8da491bf 100644 --- a/src/widgets/styles/qmacstyle.qdoc +++ b/src/widgets/styles/qmacstyle.qdoc @@ -49,21 +49,21 @@ \list - \i Layout - The restrictions on window layout are such that some + \li Layout - The restrictions on window layout are such that some aspects of layout that are style-dependent cannot be achieved using QLayout. Changes are being considered (and feedback would be appreciated) to make layouts QStyle-able. Some of the restrictions involve horizontal and vertical widget alignment and widget size (covered below). - \i Widget size - Mac OS X allows widgets to have specific fixed sizes. Qt + \li Widget size - Mac OS X allows widgets to have specific fixed sizes. Qt does not fully implement this behavior so as to maintain cross-platform compatibility. As a result some widgets sizes may be inappropriate (and subsequently not rendered correctly by the HITheme APIs).The QWidget::sizeHint() will return the appropriate size for many managed widgets (widgets enumerated in \l QStyle::ContentsType). - \i Effects - QMacStyle uses HITheme for performing most of the drawing, but + \li Effects - QMacStyle uses HITheme for performing most of the drawing, but also uses emulation in a few cases where HITheme does not provide the required functionality (for example, tab bars on Panther, the toolbar separator, etc). We tried to make the emulation as close to the original as diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 3ff5aea0ca..db387fecec 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -124,10 +124,10 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C Most QStyle draw functions take four arguments: \list - \o an enum value specifying which graphical element to draw - \o a QStyleOption specifying how and where to render that element - \o a QPainter that should be used to draw the element - \o a QWidget on which the drawing is performed (optional) + \li an enum value specifying which graphical element to draw + \li a QStyleOption specifying how and where to render that element + \li a QPainter that should be used to draw the element + \li a QWidget on which the drawing is performed (optional) \endlist For example, if you want to draw a focus rectangle on your @@ -275,12 +275,12 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C right-to-left environment: \list - \o subControlRect() and subElementRect() return rectangles in screen coordinates - \o QStyleOption::direction indicates in which direction the item should be drawn in - \o If a style is not right-to-left aware it will display items as if it were left-to-right - \o visualRect(), visualPos(), and visualAlignment() are helpful functions that will + \li subControlRect() and subElementRect() return rectangles in screen coordinates + \li QStyleOption::direction indicates in which direction the item should be drawn in + \li If a style is not right-to-left aware it will display items as if it were left-to-right + \li visualRect(), visualPos(), and visualAlignment() are helpful functions that will translate from logical to screen representations. - \o alignedRect() will return a logical rect aligned for the current direction + \li alignedRect() will return a logical rect aligned for the current direction \endlist \section1 Styles in Item Views @@ -731,50 +731,50 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, it uses a plain QStyleOption object. \table - \header \o Primitive Element \o QStyleOption Subclass \o Style Flag \o Remark - \row \o \l PE_FrameFocusRect \o \l QStyleOptionFocusRect - \o \l State_FocusAtBorder - \o Whether the focus is is at the border or inside the widget. - \row \o{1,2} \l PE_IndicatorCheckBox \o{1,2} \l QStyleOptionButton - \o \l State_NoChange \o Indicates a "tri-state" checkbox. - \row \o \l State_On \o Indicates the indicator is checked. - \row \o \l PE_IndicatorRadioButton \o \l QStyleOptionButton - \o \l State_On \o Indicates that a radio button is selected. - \row \o{1,3} \l PE_Q3CheckListExclusiveIndicator, \l PE_Q3CheckListIndicator - \o{1,3} \l QStyleOptionQ3ListView \o \l State_On - \o Indicates whether or not the controller is selected. - \row \o \l State_NoChange \o Indicates a "tri-state" controller. - \row \o \l State_Enabled \o Indicates the controller is enabled. - \row \o{1,4} \l PE_IndicatorBranch \o{1,4} \l QStyleOption - \o \l State_Children \o Indicates that the control for expanding the tree to show child items, should be drawn. - \row \o \l State_Item \o Indicates that a horizontal branch (to show a child item), should be drawn. - \row \o \l State_Open \o Indicates that the tree branch is expanded. - \row \o \l State_Sibling \o Indicates that a vertical line (to show a sibling item), should be drawn. - \row \o \l PE_IndicatorHeaderArrow \o \l QStyleOptionHeader - \o \l State_UpArrow \o Indicates that the arrow should be drawn up; + \header \li Primitive Element \li QStyleOption Subclass \li Style Flag \li Remark + \row \li \l PE_FrameFocusRect \li \l QStyleOptionFocusRect + \li \l State_FocusAtBorder + \li Whether the focus is is at the border or inside the widget. + \row \li{1,2} \l PE_IndicatorCheckBox \li{1,2} \l QStyleOptionButton + \li \l State_NoChange \li Indicates a "tri-state" checkbox. + \row \li \l State_On \li Indicates the indicator is checked. + \row \li \l PE_IndicatorRadioButton \li \l QStyleOptionButton + \li \l State_On \li Indicates that a radio button is selected. + \row \li{1,3} \l PE_Q3CheckListExclusiveIndicator, \l PE_Q3CheckListIndicator + \li{1,3} \l QStyleOptionQ3ListView \li \l State_On + \li Indicates whether or not the controller is selected. + \row \li \l State_NoChange \li Indicates a "tri-state" controller. + \row \li \l State_Enabled \li Indicates the controller is enabled. + \row \li{1,4} \l PE_IndicatorBranch \li{1,4} \l QStyleOption + \li \l State_Children \li Indicates that the control for expanding the tree to show child items, should be drawn. + \row \li \l State_Item \li Indicates that a horizontal branch (to show a child item), should be drawn. + \row \li \l State_Open \li Indicates that the tree branch is expanded. + \row \li \l State_Sibling \li Indicates that a vertical line (to show a sibling item), should be drawn. + \row \li \l PE_IndicatorHeaderArrow \li \l QStyleOptionHeader + \li \l State_UpArrow \li Indicates that the arrow should be drawn up; otherwise it should be down. - \row \o \l PE_FrameGroupBox, \l PE_Frame, \l PE_FrameLineEdit, + \row \li \l PE_FrameGroupBox, \l PE_Frame, \l PE_FrameLineEdit, \l PE_FrameMenu, \l PE_FrameDockWidget, \l PE_FrameWindow - \o \l QStyleOptionFrame \o \l State_Sunken - \o Indicates that the Frame should be sunken. - \row \o \l PE_IndicatorToolBarHandle \o \l QStyleOption - \o \l State_Horizontal \o Indicates that the window handle is horizontal + \li \l QStyleOptionFrame \li \l State_Sunken + \li Indicates that the Frame should be sunken. + \row \li \l PE_IndicatorToolBarHandle \li \l QStyleOption + \li \l State_Horizontal \li Indicates that the window handle is horizontal instead of vertical. - \row \o \l PE_Q3DockWindowSeparator \o \l QStyleOption - \o \l State_Horizontal \o Indicates that the separator is horizontal + \row \li \l PE_Q3DockWindowSeparator \li \l QStyleOption + \li \l State_Horizontal \li Indicates that the separator is horizontal instead of vertical. - \row \o \l PE_IndicatorSpinPlus, \l PE_IndicatorSpinMinus, \l PE_IndicatorSpinUp, + \row \li \l PE_IndicatorSpinPlus, \l PE_IndicatorSpinMinus, \l PE_IndicatorSpinUp, \l PE_IndicatorSpinDown, - \o \l QStyleOptionSpinBox - \o \l State_Sunken \o Indicates that the button is pressed. - \row \o{1,5} \l PE_PanelButtonCommand - \o{1,5} \l QStyleOptionButton - \o \l State_Enabled \o Set if the button is enabled. - \row \o \l State_HasFocus \o Set if the button has input focus. - \row \o \l State_Raised \o Set if the button is not down, not on and not flat. - \row \o \l State_On \o Set if the button is a toggle button and is toggled on. - \row \o \l State_Sunken - \o Set if the button is down (i.e., the mouse button or the + \li \l QStyleOptionSpinBox + \li \l State_Sunken \li Indicates that the button is pressed. + \row \li{1,5} \l PE_PanelButtonCommand + \li{1,5} \l QStyleOptionButton + \li \l State_Enabled \li Set if the button is enabled. + \row \li \l State_HasFocus \li Set if the button has input focus. + \row \li \l State_Raised \li Set if the button is not down, not on and not flat. + \row \li \l State_On \li Set if the button is a toggle button and is toggled on. + \row \li \l State_Sunken + \li Set if the button is down (i.e., the mouse button or the space bar is pressed on the button). \endtable @@ -887,69 +887,69 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, it uses a plain QStyleOption object. \table - \header \o Control Element \o QStyleOption Subclass \o Style Flag \o Remark - \row \o{1,5} \l CE_MenuItem, \l CE_MenuBarItem - \o{1,5} \l QStyleOptionMenuItem - \o \l State_Selected \o The menu item is currently selected item. - \row \o \l State_Enabled \o The item is enabled. - \row \o \l State_DownArrow \o Indicates that a scroll down arrow should be drawn. - \row \o \l State_UpArrow \o Indicates that a scroll up arrow should be drawn - \row \o \l State_HasFocus \o Set if the menu bar has input focus. - - \row \o{1,5} \l CE_PushButton, \l CE_PushButtonBevel, \l CE_PushButtonLabel - \o{1,5} \l QStyleOptionButton - \o \l State_Enabled \o Set if the button is enabled. - \row \o \l State_HasFocus \o Set if the button has input focus. - \row \o \l State_Raised \o Set if the button is not down, not on and not flat. - \row \o \l State_On \o Set if the button is a toggle button and is toggled on. - \row \o \l State_Sunken - \o Set if the button is down (i.e., the mouse button or the + \header \li Control Element \li QStyleOption Subclass \li Style Flag \li Remark + \row \li{1,5} \l CE_MenuItem, \l CE_MenuBarItem + \li{1,5} \l QStyleOptionMenuItem + \li \l State_Selected \li The menu item is currently selected item. + \row \li \l State_Enabled \li The item is enabled. + \row \li \l State_DownArrow \li Indicates that a scroll down arrow should be drawn. + \row \li \l State_UpArrow \li Indicates that a scroll up arrow should be drawn + \row \li \l State_HasFocus \li Set if the menu bar has input focus. + + \row \li{1,5} \l CE_PushButton, \l CE_PushButtonBevel, \l CE_PushButtonLabel + \li{1,5} \l QStyleOptionButton + \li \l State_Enabled \li Set if the button is enabled. + \row \li \l State_HasFocus \li Set if the button has input focus. + \row \li \l State_Raised \li Set if the button is not down, not on and not flat. + \row \li \l State_On \li Set if the button is a toggle button and is toggled on. + \row \li \l State_Sunken + \li Set if the button is down (i.e., the mouse button or the space bar is pressed on the button). - \row \o{1,6} \l CE_RadioButton, \l CE_RadioButtonLabel, + \row \li{1,6} \l CE_RadioButton, \l CE_RadioButtonLabel, \l CE_CheckBox, \l CE_CheckBoxLabel - \o{1,6} \l QStyleOptionButton - \o \l State_Enabled \o Set if the button is enabled. - \row \o \l State_HasFocus \o Set if the button has input focus. - \row \o \l State_On \o Set if the button is checked. - \row \o \l State_Off \o Set if the button is not checked. - \row \o \l State_NoChange \o Set if the button is in the NoChange state. - \row \o \l State_Sunken - \o Set if the button is down (i.e., the mouse button or + \li{1,6} \l QStyleOptionButton + \li \l State_Enabled \li Set if the button is enabled. + \row \li \l State_HasFocus \li Set if the button has input focus. + \row \li \l State_On \li Set if the button is checked. + \row \li \l State_Off \li Set if the button is not checked. + \row \li \l State_NoChange \li Set if the button is in the NoChange state. + \row \li \l State_Sunken + \li Set if the button is down (i.e., the mouse button or the space bar is pressed on the button). - \row \o{1,2} \l CE_ProgressBarContents, \l CE_ProgressBarLabel, + \row \li{1,2} \l CE_ProgressBarContents, \l CE_ProgressBarLabel, \l CE_ProgressBarGroove - \o{1,2} \l QStyleOptionProgressBar - \o \l State_Enabled \o Set if the progress bar is enabled. - \row \o \l State_HasFocus \o Set if the progress bar has input focus. - - \row \o \l CE_Header, \l CE_HeaderSection, \l CE_HeaderLabel \o \l QStyleOptionHeader \o \o - - \row \o{1,3} \l CE_TabBarTab, CE_TabBarTabShape, CE_TabBarTabLabel - \o{1,3} \l QStyleOptionTab - \o \l State_Enabled \o Set if the tab bar is enabled. - \row \o \l State_Selected \o The tab bar is the currently selected tab bar. - \row \o \l State_HasFocus \o Set if the tab bar tab has input focus. - - \row \o{1,7} \l CE_ToolButtonLabel - \o{1,7} \l QStyleOptionToolButton - \o \l State_Enabled \o Set if the tool button is enabled. - \row \o \l State_HasFocus \o Set if the tool button has input focus. - \row \o \l State_Sunken - \o Set if the tool button is down (i.e., a mouse button or + \li{1,2} \l QStyleOptionProgressBar + \li \l State_Enabled \li Set if the progress bar is enabled. + \row \li \l State_HasFocus \li Set if the progress bar has input focus. + + \row \li \l CE_Header, \l CE_HeaderSection, \l CE_HeaderLabel \li \l QStyleOptionHeader \li \li + + \row \li{1,3} \l CE_TabBarTab, CE_TabBarTabShape, CE_TabBarTabLabel + \li{1,3} \l QStyleOptionTab + \li \l State_Enabled \li Set if the tab bar is enabled. + \row \li \l State_Selected \li The tab bar is the currently selected tab bar. + \row \li \l State_HasFocus \li Set if the tab bar tab has input focus. + + \row \li{1,7} \l CE_ToolButtonLabel + \li{1,7} \l QStyleOptionToolButton + \li \l State_Enabled \li Set if the tool button is enabled. + \row \li \l State_HasFocus \li Set if the tool button has input focus. + \row \li \l State_Sunken + \li Set if the tool button is down (i.e., a mouse button or the space bar is pressed). - \row \o \l State_On \o Set if the tool button is a toggle button and is toggled on. - \row \o \l State_AutoRaise \o Set if the tool button has auto-raise enabled. - \row \o \l State_MouseOver \o Set if the mouse pointer is over the tool button. - \row \o \l State_Raised \o Set if the button is not down and is not on. - - \row \o \l CE_ToolBoxTab \o \l QStyleOptionToolBox - \o \l State_Selected \o The tab is the currently selected tab. - \row \o{1,3} \l CE_HeaderSection \o{1,3} \l QStyleOptionHeader - \o \l State_Sunken \o Indicates that the section is pressed. - \row \o \l State_UpArrow \o Indicates that the sort indicator should be pointing up. - \row \o \l State_DownArrow \o Indicates that the sort indicator should be pointing down. + \row \li \l State_On \li Set if the tool button is a toggle button and is toggled on. + \row \li \l State_AutoRaise \li Set if the tool button has auto-raise enabled. + \row \li \l State_MouseOver \li Set if the mouse pointer is over the tool button. + \row \li \l State_Raised \li Set if the button is not down and is not on. + + \row \li \l CE_ToolBoxTab \li \l QStyleOptionToolBox + \li \l State_Selected \li The tab is the currently selected tab. + \row \li{1,3} \l CE_HeaderSection \li{1,3} \l QStyleOptionHeader + \li \l State_Sunken \li Indicates that the section is pressed. + \row \li \l State_UpArrow \li Indicates that the sort indicator should be pointing up. + \row \li \l State_DownArrow \li Indicates that the sort indicator should be pointing down. \endtable \sa drawPrimitive(), drawComplexControl() @@ -1077,20 +1077,20 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, table below for the appropriate \a option casts: \table - \header \o Sub Element \o QStyleOption Subclass - \row \o \l SE_PushButtonContents \o \l QStyleOptionButton - \row \o \l SE_PushButtonFocusRect \o \l QStyleOptionButton - \row \o \l SE_CheckBoxIndicator \o \l QStyleOptionButton - \row \o \l SE_CheckBoxContents \o \l QStyleOptionButton - \row \o \l SE_CheckBoxFocusRect \o \l QStyleOptionButton - \row \o \l SE_RadioButtonIndicator \o \l QStyleOptionButton - \row \o \l SE_RadioButtonContents \o \l QStyleOptionButton - \row \o \l SE_RadioButtonFocusRect \o \l QStyleOptionButton - \row \o \l SE_ComboBoxFocusRect \o \l QStyleOptionComboBox - \row \o \l SE_Q3DockWindowHandleRect \o \l QStyleOptionQ3DockWindow - \row \o \l SE_ProgressBarGroove \o \l QStyleOptionProgressBar - \row \o \l SE_ProgressBarContents \o \l QStyleOptionProgressBar - \row \o \l SE_ProgressBarLabel \o \l QStyleOptionProgressBar + \header \li Sub Element \li QStyleOption Subclass + \row \li \l SE_PushButtonContents \li \l QStyleOptionButton + \row \li \l SE_PushButtonFocusRect \li \l QStyleOptionButton + \row \li \l SE_CheckBoxIndicator \li \l QStyleOptionButton + \row \li \l SE_CheckBoxContents \li \l QStyleOptionButton + \row \li \l SE_CheckBoxFocusRect \li \l QStyleOptionButton + \row \li \l SE_RadioButtonIndicator \li \l QStyleOptionButton + \row \li \l SE_RadioButtonContents \li \l QStyleOptionButton + \row \li \l SE_RadioButtonFocusRect \li \l QStyleOptionButton + \row \li \l SE_ComboBoxFocusRect \li \l QStyleOptionComboBox + \row \li \l SE_Q3DockWindowHandleRect \li \l QStyleOptionQ3DockWindow + \row \li \l SE_ProgressBarGroove \li \l QStyleOptionProgressBar + \row \li \l SE_ProgressBarContents \li \l QStyleOptionProgressBar + \row \li \l SE_ProgressBarLabel \li \l QStyleOptionProgressBar \endtable */ @@ -1222,43 +1222,43 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, appropriate subclass. \table - \header \o Complex Control \o QStyleOptionComplex Subclass \o Style Flag \o Remark - \row \o{1,2} \l{CC_SpinBox} \o{1,2} \l QStyleOptionSpinBox - \o \l State_Enabled \o Set if the spin box is enabled. - \row \o \l State_HasFocus \o Set if the spin box has input focus. - - \row \o{1,2} \l {CC_ComboBox} \o{1,2} \l QStyleOptionComboBox - \o \l State_Enabled \o Set if the combobox is enabled. - \row \o \l State_HasFocus \o Set if the combobox has input focus. - - \row \o{1,2} \l {CC_ScrollBar} \o{1,2} \l QStyleOptionSlider - \o \l State_Enabled \o Set if the scroll bar is enabled. - \row \o \l State_HasFocus \o Set if the scroll bar has input focus. - - \row \o{1,2} \l {CC_Slider} \o{1,2} \l QStyleOptionSlider - \o \l State_Enabled \o Set if the slider is enabled. - \row \o \l State_HasFocus \o Set if the slider has input focus. - - \row \o{1,2} \l {CC_Dial} \o{1,2} \l QStyleOptionSlider - \o \l State_Enabled \o Set if the dial is enabled. - \row \o \l State_HasFocus \o Set if the dial has input focus. - - \row \o{1,6} \l {CC_ToolButton} \o{1,6} \l QStyleOptionToolButton - \o \l State_Enabled \o Set if the tool button is enabled. - \row \o \l State_HasFocus \o Set if the tool button has input focus. - \row \o \l State_DownArrow \o Set if the tool button is down (i.e., a mouse + \header \li Complex Control \li QStyleOptionComplex Subclass \li Style Flag \li Remark + \row \li{1,2} \l{CC_SpinBox} \li{1,2} \l QStyleOptionSpinBox + \li \l State_Enabled \li Set if the spin box is enabled. + \row \li \l State_HasFocus \li Set if the spin box has input focus. + + \row \li{1,2} \l {CC_ComboBox} \li{1,2} \l QStyleOptionComboBox + \li \l State_Enabled \li Set if the combobox is enabled. + \row \li \l State_HasFocus \li Set if the combobox has input focus. + + \row \li{1,2} \l {CC_ScrollBar} \li{1,2} \l QStyleOptionSlider + \li \l State_Enabled \li Set if the scroll bar is enabled. + \row \li \l State_HasFocus \li Set if the scroll bar has input focus. + + \row \li{1,2} \l {CC_Slider} \li{1,2} \l QStyleOptionSlider + \li \l State_Enabled \li Set if the slider is enabled. + \row \li \l State_HasFocus \li Set if the slider has input focus. + + \row \li{1,2} \l {CC_Dial} \li{1,2} \l QStyleOptionSlider + \li \l State_Enabled \li Set if the dial is enabled. + \row \li \l State_HasFocus \li Set if the dial has input focus. + + \row \li{1,6} \l {CC_ToolButton} \li{1,6} \l QStyleOptionToolButton + \li \l State_Enabled \li Set if the tool button is enabled. + \row \li \l State_HasFocus \li Set if the tool button has input focus. + \row \li \l State_DownArrow \li Set if the tool button is down (i.e., a mouse button or the space bar is pressed). - \row \o \l State_On \o Set if the tool button is a toggle button + \row \li \l State_On \li Set if the tool button is a toggle button and is toggled on. - \row \o \l State_AutoRaise \o Set if the tool button has auto-raise enabled. - \row \o \l State_Raised \o Set if the button is not down, not on, and doesn't + \row \li \l State_AutoRaise \li Set if the tool button has auto-raise enabled. + \row \li \l State_Raised \li Set if the button is not down, not on, and doesn't contain the mouse when auto-raise is enabled. - \row \o \l{CC_TitleBar} \o \l QStyleOptionTitleBar - \o \l State_Enabled \o Set if the title bar is enabled. + \row \li \l{CC_TitleBar} \li \l QStyleOptionTitleBar + \li \l State_Enabled \li Set if the title bar is enabled. - \row \o \l{CC_Q3ListView} \o \l QStyleOptionQ3ListView - \o \l State_Enabled \o Set if the list view is enabled. + \row \li \l{CC_Q3ListView} \li \l QStyleOptionQ3ListView + \li \l State_Enabled \li Set if the list view is enabled. \endtable @@ -1492,17 +1492,17 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, for the appropriate \a option casts: \table - \header \o Pixel Metric \o QStyleOption Subclass - \row \o \l PM_SliderControlThickness \o \l QStyleOptionSlider - \row \o \l PM_SliderLength \o \l QStyleOptionSlider - \row \o \l PM_SliderTickmarkOffset \o \l QStyleOptionSlider - \row \o \l PM_SliderSpaceAvailable \o \l QStyleOptionSlider - \row \o \l PM_ScrollBarExtent \o \l QStyleOptionSlider - \row \o \l PM_TabBarTabOverlap \o \l QStyleOptionTab - \row \o \l PM_TabBarTabHSpace \o \l QStyleOptionTab - \row \o \l PM_TabBarTabVSpace \o \l QStyleOptionTab - \row \o \l PM_TabBarBaseHeight \o \l QStyleOptionTab - \row \o \l PM_TabBarBaseOverlap \o \l QStyleOptionTab + \header \li Pixel Metric \li QStyleOption Subclass + \row \li \l PM_SliderControlThickness \li \l QStyleOptionSlider + \row \li \l PM_SliderLength \li \l QStyleOptionSlider + \row \li \l PM_SliderTickmarkOffset \li \l QStyleOptionSlider + \row \li \l PM_SliderSpaceAvailable \li \l QStyleOptionSlider + \row \li \l PM_ScrollBarExtent \li \l QStyleOptionSlider + \row \li \l PM_TabBarTabOverlap \li \l QStyleOptionTab + \row \li \l PM_TabBarTabHSpace \li \l QStyleOptionTab + \row \li \l PM_TabBarTabVSpace \li \l QStyleOptionTab + \row \li \l PM_TabBarBaseHeight \li \l QStyleOptionTab + \row \li \l PM_TabBarBaseOverlap \li \l QStyleOptionTab \endtable Some pixel metrics are called from widgets and some are only called @@ -1568,16 +1568,16 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, See the table below for the appropriate \a option casts: \table - \header \o Contents Type \o QStyleOption Subclass - \row \o \l CT_PushButton \o \l QStyleOptionButton - \row \o \l CT_CheckBox \o \l QStyleOptionButton - \row \o \l CT_RadioButton \o \l QStyleOptionButton - \row \o \l CT_ToolButton \o \l QStyleOptionToolButton - \row \o \l CT_ComboBox \o \l QStyleOptionComboBox - \row \o \l CT_Splitter \o \l QStyleOption - \row \o \l CT_Q3DockWindow \o \l QStyleOptionQ3DockWindow - \row \o \l CT_ProgressBar \o \l QStyleOptionProgressBar - \row \o \l CT_MenuItem \o \l QStyleOptionMenuItem + \header \li Contents Type \li QStyleOption Subclass + \row \li \l CT_PushButton \li \l QStyleOptionButton + \row \li \l CT_CheckBox \li \l QStyleOptionButton + \row \li \l CT_RadioButton \li \l QStyleOptionButton + \row \li \l CT_ToolButton \li \l QStyleOptionToolButton + \row \li \l CT_ComboBox \li \l QStyleOptionComboBox + \row \li \l CT_Splitter \li \l QStyleOption + \row \li \l CT_Q3DockWindow \li \l QStyleOptionQ3DockWindow + \row \li \l CT_ProgressBar \li \l QStyleOptionProgressBar + \row \li \l CT_MenuItem \li \l QStyleOptionMenuItem \endtable \sa ContentsType QStyleOption diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp index 63e7b8775e..d72ba1bac5 100644 --- a/src/widgets/styles/qstyleoption.cpp +++ b/src/widgets/styles/qstyleoption.cpp @@ -1795,7 +1795,7 @@ QStyleOptionMenuItem::QStyleOptionMenuItem(int version) \brief the text for the menu item Note that the text format is something like this "Menu - text\bold{\\t}Shortcut". + text\b{\\t}Shortcut". If the menu item doesn't have a shortcut, it will just contain the menu item's text. The default value is an empty string. @@ -2240,7 +2240,7 @@ QStyleOptionSpinBox::QStyleOptionSpinBox(int version) \inmodule QtWidgets This class is used for drawing the compatibility Q3ListView's - items. \bold {It is not recommended for new classes}. + items. \b {It is not recommended for new classes}. QStyleOptionQ3ListViewItem contains all the information that QStyle functions need to draw the Q3ListView items. @@ -2376,7 +2376,7 @@ QStyleOptionQ3ListViewItem::QStyleOptionQ3ListViewItem(int version) \inmodule QtWidgets - This class is used for drawing the compatibility Q3ListView. \bold + This class is used for drawing the compatibility Q3ListView. \b {It is not recommended for new classes}. QStyleOptionQ3ListView contains all the information that QStyle @@ -2523,7 +2523,7 @@ QStyleOptionQ3ListView::QStyleOptionQ3ListView(int version) \inmodule QtWidgets This class is used for drawing the old Q3DockWindow and its - parts. \bold {It is not recommended for new classes}. + parts. \b {It is not recommended for new classes}. QStyleOptionQ3DockWindow contains all the information that QStyle functions need to draw Q3DockWindow and its parts. diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index d416f26f51..91e4a9c3c1 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -1475,7 +1475,7 @@ int QCompleter::completionCount() const The sort order (i.e ascending or descending order) of the model is determined dynamically by inspecting the contents of the model. - \bold{Note:} The performance improvements described above cannot take place + \b{Note:} The performance improvements described above cannot take place when the completer's \l caseSensitivity is different to the case sensitivity used by the model's when sorting. diff --git a/src/widgets/util/qscrollerproperties.cpp b/src/widgets/util/qscrollerproperties.cpp index 8d6ad36014..b698252b07 100644 --- a/src/widgets/util/qscrollerproperties.cpp +++ b/src/widgets/util/qscrollerproperties.cpp @@ -329,7 +329,7 @@ void QScrollerProperties::setScrollMetric(ScrollMetric metric, const QVariant &v around the axis. The threshold must be in the range \c 0 to \c 1. \value ScrollingCurve The QEasingCurve used when decelerating the scrolling velocity after an - user initiated flick. Please note that this is the easing curve for the positions, \bold{not} + user initiated flick. Please note that this is the easing curve for the positions, \b{not} the velocity: the default is QEasingCurve::OutQuad, which results in a linear decrease in velocity (1st derivative) and a constant deceleration (2nd derivative). diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index bed8dc2eae..fc2d046114 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -77,10 +77,10 @@ QT_BEGIN_NAMESPACE The QSystemTrayIcon class can be used on the following platforms: \list - \o All supported versions of Windows. - \o All window managers for X11 that implement the \l{freedesktop.org} system + \li All supported versions of Windows. + \li All window managers for X11 that implement the \l{freedesktop.org} system tray specification, including recent versions of KDE and GNOME. - \o All supported versions of Mac OS X. Note that the Growl + \li All supported versions of Mac OS X. Note that the Growl notification system must be installed for QSystemTrayIcon::showMessage() to display messages. \endlist diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 7cd77678e6..5392dd2f8e 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -934,10 +934,10 @@ QAction *QUndoStack::createRedoAction(QObject *parent, const QString &prefix) co While a macro is composed, the stack is disabled. This means that: \list - \i indexChanged() and cleanChanged() are not emitted, - \i canUndo() and canRedo() return false, - \i calling undo() or redo() has no effect, - \i the undo/redo actions are disabled. + \li indexChanged() and cleanChanged() are not emitted, + \li canUndo() and canRedo() return false, + \li calling undo() or redo() has no effect, + \li the undo/redo actions are disabled. \endlist The stack becomes enabled and appropriate signals are emitted when endMacro() diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index be250c54e1..2c51e89c43 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -109,21 +109,21 @@ Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets; \list - \o isDown() indicates whether the button is \e pressed down. + \li isDown() indicates whether the button is \e pressed down. - \o isChecked() indicates whether the button is \e checked. Only + \li isChecked() indicates whether the button is \e checked. Only checkable buttons can be checked and unchecked (see below). - \o isEnabled() indicates whether the button can be pressed by the + \li isEnabled() indicates whether the button can be pressed by the user. \note As opposed to other widgets, buttons derived from QAbstractButton accepts mouse and context menu events when disabled. - \o setAutoRepeat() sets whether the button will auto-repeat if the + \li setAutoRepeat() sets whether the button will auto-repeat if the user holds it down. \l autoRepeatDelay and \l autoRepeatInterval define how auto-repetition is done. - \o setCheckable() sets whether the button is a toggle button or not. + \li setCheckable() sets whether the button is a toggle button or not. \endlist @@ -138,16 +138,16 @@ Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets; \list 1 - \o pressed() is emitted when the left mouse button is pressed while + \li pressed() is emitted when the left mouse button is pressed while the mouse cursor is inside the button. - \o released() is emitted when the left mouse button is released. + \li released() is emitted when the left mouse button is released. - \o clicked() is emitted when the button is first pressed and then + \li clicked() is emitted when the button is first pressed and then released, when the shortcut key is typed, or when click() or animateClick() is called. - \o toggled() is emitted when the state of a toggle button changes. + \li toggled() is emitted when the state of a toggle button changes. \endlist diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 03ec21680d..a960ce8d9c 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -101,14 +101,14 @@ QT_BEGIN_NAMESPACE following: \list - \o Control the scroll bars by setting their + \li Control the scroll bars by setting their range, value, page step, and tracking their movements. - \o Draw the contents of the area in the viewport according + \li Draw the contents of the area in the viewport according to the values of the scroll bars. - \o Handle events received by the viewport in + \li Handle events received by the viewport in viewportEvent() - notably resize events. - \o Use \c{viewport->update()} to update the contents of the + \li Use \c{viewport->update()} to update the contents of the viewport instead of \l{QWidget::update()}{update()} as all painting operations take place on the viewport. \endlist diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index be193f64f0..6aff2e9077 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -65,23 +65,23 @@ QT_BEGIN_NAMESPACE \list 1 - \i \l value: The bounded integer that QAbstractSlider maintains. + \li \l value: The bounded integer that QAbstractSlider maintains. - \i \l minimum: The lowest possible value. + \li \l minimum: The lowest possible value. - \i \l maximum: The highest possible value. + \li \l maximum: The highest possible value. - \i \l singleStep: The smaller of two natural steps that an + \li \l singleStep: The smaller of two natural steps that an abstract sliders provides and typically corresponds to the user pressing an arrow key. - \i \l pageStep: The larger of two natural steps that an abstract + \li \l pageStep: The larger of two natural steps that an abstract slider provides and typically corresponds to the user pressing PageUp or PageDown. - \i \l tracking: Whether slider tracking is enabled. + \li \l tracking: Whether slider tracking is enabled. - \i \l sliderPosition: The current position of the slider. If \l + \li \l sliderPosition: The current position of the slider. If \l tracking is enabled (the default), this is identical to \l value. \endlist @@ -95,21 +95,21 @@ QT_BEGIN_NAMESPACE QAbstractSlider emits a comprehensive set of signals: \table - \header \i Signal \i Emitted when - \row \i \l valueChanged() - \i the value has changed. The \l tracking + \header \li Signal \li Emitted when + \row \li \l valueChanged() + \li the value has changed. The \l tracking determines whether this signal is emitted during user interaction. - \row \i \l sliderPressed() - \i the user starts to drag the slider. - \row \i \l sliderMoved() - \i the user drags the slider. - \row \i \l sliderReleased() - \i the user releases the slider. - \row \i \l actionTriggered() - \i a slider action was triggerd. - \row \i \l rangeChanged() - \i a the range has changed. + \row \li \l sliderPressed() + \li the user starts to drag the slider. + \row \li \l sliderMoved() + \li the user drags the slider. + \row \li \l sliderReleased() + \li the user releases the slider. + \row \li \l actionTriggered() + \li a slider action was triggerd. + \row \li \l rangeChanged() + \li a the range has changed. \endtable QAbstractSlider provides a virtual sliderChange() function that is diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 331b4918bd..e9652a9869 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -90,11 +90,11 @@ QT_BEGIN_NAMESPACE \list 1 - \i \l text: The text that is displayed in the QAbstractSpinBox. + \li \l text: The text that is displayed in the QAbstractSpinBox. - \i \l alignment: The alignment of the text in the QAbstractSpinBox. + \li \l alignment: The alignment of the text in the QAbstractSpinBox. - \i \l wrapping: Whether the QAbstractSpinBox wraps from the + \li \l wrapping: Whether the QAbstractSpinBox wraps from the minimum value to the maximum value and vica versa. \endlist @@ -167,7 +167,7 @@ QAbstractSpinBox::~QAbstractSpinBox() \inlineimage qspinbox-plusminus.png \value UpDownArrows Little arrows in the classic style. - \value PlusMinus \bold{+} and \bold{-} symbols. + \value PlusMinus \b{+} and \b{-} symbols. \value NoButtons Don't display buttons. \sa QAbstractSpinBox::buttonSymbols @@ -918,17 +918,17 @@ void QAbstractSpinBox::paintEvent(QPaintEvent *) The following keys are handled specifically: \table - \row \i Enter/Return - \i This will reinterpret the text and emit a signal even if the value has not changed + \row \li Enter/Return + \li This will reinterpret the text and emit a signal even if the value has not changed since last time a signal was emitted. - \row \i Up - \i This will invoke stepBy(1) - \row \i Down - \i This will invoke stepBy(-1) - \row \i Page up - \i This will invoke stepBy(10) - \row \i Page down - \i This will invoke stepBy(-10) + \row \li Up + \li This will invoke stepBy(1) + \row \li Down + \li This will invoke stepBy(-1) + \row \li Page up + \li This will invoke stepBy(10) + \row \li Page down + \li This will invoke stepBy(-10) \endtable */ diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 1541010646..129da9d94d 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -2001,9 +2001,9 @@ void QCalendarWidgetPrivate::_q_editingFinished() setGridVisible() function: \table - \row \o + \row \li \image qcalendarwidget-grid.png - \row \o + \row \li \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 0 \endtable @@ -2418,9 +2418,9 @@ void QCalendarWidget::showToday() \table \row - \o \image qcalendarwidget-minimum.png + \li \image qcalendarwidget-minimum.png \row - \o + \li \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 1 \endtable @@ -2469,9 +2469,9 @@ void QCalendarWidget::setMinimumDate(const QDate &date) \table \row - \o \image qcalendarwidget-maximum.png + \li \image qcalendarwidget-maximum.png \row - \o + \li \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 2 \endtable @@ -2638,9 +2638,9 @@ void QCalendarWidget::setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFor \table \row - \o \inlineimage qcalendarwidget-grid.png + \li \inlineimage qcalendarwidget-grid.png \row - \o + \li \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 5 \endtable diff --git a/src/widgets/widgets/qcheckbox.cpp b/src/widgets/widgets/qcheckbox.cpp index 3bf2e39ef1..13440ac104 100644 --- a/src/widgets/widgets/qcheckbox.cpp +++ b/src/widgets/widgets/qcheckbox.cpp @@ -87,8 +87,8 @@ public: non-exclusive checkboxes. \table - \row \o \inlineimage checkboxes-exclusive.png - \o \inlineimage checkboxes-non-exclusive.png + \row \li \inlineimage checkboxes-exclusive.png + \li \inlineimage checkboxes-non-exclusive.png \endtable Whenever a checkbox is checked or cleared it emits the signal @@ -121,14 +121,14 @@ public: \table 100% \row - \o \inlineimage macintosh-checkbox.png Screenshot of a Macintosh style checkbox - \o A checkbox shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \li \inlineimage macintosh-checkbox.png Screenshot of a Macintosh style checkbox + \li A checkbox shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. \row - \o \inlineimage windows-checkbox.png Screenshot of a Windows XP style checkbox - \o A checkbox shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \li \inlineimage windows-checkbox.png Screenshot of a Windows XP style checkbox + \li A checkbox shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. \row - \o \inlineimage plastique-checkbox.png Screenshot of a Plastique style checkbox - \o A checkbox shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \li \inlineimage plastique-checkbox.png Screenshot of a Plastique style checkbox + \li A checkbox shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QAbstractButton, QRadioButton, {fowler}{GUI Design Handbook: Check Box} diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index 5761c1299c..3d0996a9f5 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -103,12 +103,12 @@ QT_BEGIN_NAMESPACE calendar widget can be retrieved with calendarWidget(). \table 100% - \row \o \inlineimage windowsxp-datetimeedit.png Screenshot of a Windows XP style date time editing widget - \o A date time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage macintosh-datetimeedit.png Screenshot of a Macintosh style date time editing widget - \o A date time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage plastique-datetimeedit.png Screenshot of a Plastique style date time editing widget - \o A date time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage windowsxp-datetimeedit.png Screenshot of a Windows XP style date time editing widget + \li A date time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage macintosh-datetimeedit.png Screenshot of a Macintosh style date time editing widget + \li A date time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage plastique-datetimeedit.png Screenshot of a Plastique style date time editing widget + \li A date time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QDateEdit, QTimeEdit, QDate, QTime @@ -835,10 +835,10 @@ QString QDateTimeEdit::sectionText(Section section) const Example format strings (assuming that the date is 2nd of July 1969): \table - \header \i Format \i Result - \row \i dd.MM.yyyy \i 02.07.1969 - \row \i MMM d yy \i Jul 2 69 - \row \i MMMM d yy \i July 2 69 + \header \li Format \li Result + \row \li dd.MM.yyyy \li 02.07.1969 + \row \li MMM d yy \li Jul 2 69 + \row \li MMMM d yy \li July 2 69 \endtable Note that if you specify a two digit year, it will be interpreted @@ -1520,22 +1520,22 @@ void QDateTimeEdit::mousePressEvent(QMouseEvent *event) class: \list - \o \l{QDateTimeEdit::time}{time} holds the date displayed by the widget. - \o \l{QDateTimeEdit::minimumTime}{minimumTime} defines the minimum (earliest) time + \li \l{QDateTimeEdit::time}{time} holds the date displayed by the widget. + \li \l{QDateTimeEdit::minimumTime}{minimumTime} defines the minimum (earliest) time that can be set by the user. - \o \l{QDateTimeEdit::maximumTime}{maximumTime} defines the maximum (latest) time + \li \l{QDateTimeEdit::maximumTime}{maximumTime} defines the maximum (latest) time that can be set by the user. - \o \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used + \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used to format the time displayed in the widget. \endlist \table 100% - \row \o \inlineimage windowsxp-timeedit.png Screenshot of a Windows XP style time editing widget - \o A time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage macintosh-timeedit.png Screenshot of a Macintosh style time editing widget - \o A time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage plastique-timeedit.png Screenshot of a Plastique style time editing widget - \o A time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage windowsxp-timeedit.png Screenshot of a Windows XP style time editing widget + \li A time editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage macintosh-timeedit.png Screenshot of a Macintosh style time editing widget + \li A time editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage plastique-timeedit.png Screenshot of a Plastique style time editing widget + \li A time editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QDateEdit, QDateTimeEdit @@ -1575,22 +1575,22 @@ QTimeEdit::QTimeEdit(const QTime &time, QWidget *parent) class: \list - \o \l{QDateTimeEdit::date}{date} holds the date displayed by the widget. - \o \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest) + \li \l{QDateTimeEdit::date}{date} holds the date displayed by the widget. + \li \l{QDateTimeEdit::minimumDate}{minimumDate} defines the minimum (earliest) date that can be set by the user. - \o \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date + \li \l{QDateTimeEdit::maximumDate}{maximumDate} defines the maximum (latest) date that can be set by the user. - \o \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used + \li \l{QDateTimeEdit::displayFormat}{displayFormat} contains a string that is used to format the date displayed in the widget. \endlist \table 100% - \row \o \inlineimage windowsxp-dateedit.png Screenshot of a Windows XP style date editing widget - \o A date editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget - \o A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage plastique-dateedit.png Screenshot of a Plastique style date editing widget - \o A date editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage windowsxp-dateedit.png Screenshot of a Windows XP style date editing widget + \li A date editing widget shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage macintosh-dateedit.png Screenshot of a Macintosh style date editing widget + \li A date editing widget shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage plastique-dateedit.png Screenshot of a Plastique style date editing widget + \li A date editing widget shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QTimeEdit, QDateTimeEdit diff --git a/src/widgets/widgets/qdial.cpp b/src/widgets/widgets/qdial.cpp index 566652b8f5..e3fe390f2a 100644 --- a/src/widgets/widgets/qdial.cpp +++ b/src/widgets/widgets/qdial.cpp @@ -230,10 +230,10 @@ int QDialPrivate::valueFromPoint(const QPoint &p) const \l {QAbstractSlider::pageStep} {pageStep}. \table - \row \o \inlineimage plastique-dial.png Screenshot of a dial in the Plastique widget style - \o \inlineimage windowsxp-dial.png Screenshot of a dial in the Windows XP widget style - \o \inlineimage macintosh-dial.png Screenshot of a dial in the Macintosh widget style - \row \o {3,1} Dials shown in various widget styles (from left to right): + \row \li \inlineimage plastique-dial.png Screenshot of a dial in the Plastique widget style + \li \inlineimage windowsxp-dial.png Screenshot of a dial in the Windows XP widget style + \li \inlineimage macintosh-dial.png Screenshot of a dial in the Macintosh widget style + \row \li {3,1} Dials shown in various widget styles (from left to right): \l{Plastique Style Widget Gallery}{Plastique}, \l{Windows XP Style Widget Gallery}{Windows XP}, \l{Macintosh Style Widget Gallery}{Macintosh}. diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index d1084168a9..14643e77f6 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -76,9 +76,9 @@ QT_BEGIN_NAMESPACE Most buttons for a dialog follow certain roles. Such roles include: \list - \o Accepting or rejecting the dialog. - \o Asking for help. - \o Performing actions on the dialog itself (such as resetting fields or + \li Accepting or rejecting the dialog. + \li Asking for help. + \li Performing actions on the dialog itself (such as resetting fields or applying changes). \endlist @@ -104,35 +104,35 @@ QT_BEGIN_NAMESPACE Currently the buttons are laid out in the following way if the button box is horizontal: \table - \row \o \inlineimage buttonbox-gnomelayout-horizontal.png GnomeLayout Horizontal - \o Button box laid out in horizontal GnomeLayout - \row \o \inlineimage buttonbox-kdelayout-horizontal.png KdeLayout Horizontal - \o Button box laid out in horizontal KdeLayout - \row \o \inlineimage buttonbox-maclayout-horizontal.png MacLayout Horizontal - \o Button box laid out in horizontal MacLayout - \row \o \inlineimage buttonbox-winlayout-horizontal.png WinLayout Horizontal - \o Button box laid out in horizontal WinLayout + \row \li \inlineimage buttonbox-gnomelayout-horizontal.png GnomeLayout Horizontal + \li Button box laid out in horizontal GnomeLayout + \row \li \inlineimage buttonbox-kdelayout-horizontal.png KdeLayout Horizontal + \li Button box laid out in horizontal KdeLayout + \row \li \inlineimage buttonbox-maclayout-horizontal.png MacLayout Horizontal + \li Button box laid out in horizontal MacLayout + \row \li \inlineimage buttonbox-winlayout-horizontal.png WinLayout Horizontal + \li Button box laid out in horizontal WinLayout \endtable The buttons are laid out the following way if the button box is vertical: \table - \row \o GnomeLayout - \o KdeLayout - \o MacLayout - \o WinLayout - \row \o \inlineimage buttonbox-gnomelayout-vertical.png GnomeLayout Vertical - \o \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical - \o \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical - \o \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical + \row \li GnomeLayout + \li KdeLayout + \li MacLayout + \li WinLayout + \row \li \inlineimage buttonbox-gnomelayout-vertical.png GnomeLayout Vertical + \li \inlineimage buttonbox-kdelayout-vertical.png KdeLayout Vertical + \li \inlineimage buttonbox-maclayout-vertical.png MacLayout Vertical + \li \inlineimage buttonbox-winlayout-vertical.png WinLayout Vertical \endtable Additionally, button boxes that contain only buttons with ActionRole or HelpRole can be considered modeless and have an alternate look on Mac OS X: \table - \row \o modeless horizontal MacLayout - \o \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout + \row \li modeless horizontal MacLayout + \li \inlineimage buttonbox-mac-modeless-horizontal.png Screenshot of modeless horizontal MacLayout \endtable When a button is clicked in the button box, the clicked() signal is emitted diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index a90c754cee..e40b109455 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1538,22 +1538,22 @@ QAction * QDockWidget::toggleViewAction() const Here are some tips for implementing custom title bars: \list - \o Mouse events that are not explicitly handled by the title bar widget + \li Mouse events that are not explicitly handled by the title bar widget must be ignored by calling QMouseEvent::ignore(). These events then propagate to the QDockWidget parent, which handles them in the usual manner, moving when the title bar is dragged, docking and undocking when it is double-clicked, etc. - \o When DockWidgetVerticalTitleBar is set on QDockWidget, the title + \li When DockWidgetVerticalTitleBar is set on QDockWidget, the title bar widget is repositioned accordingly. In resizeEvent(), the title bar should check what orientation it should assume: \snippet doc/src/snippets/code/src_gui_widgets_qdockwidget.cpp 0 - \o The title bar widget must have a valid QWidget::sizeHint() and + \li The title bar widget must have a valid QWidget::sizeHint() and QWidget::minimumSizeHint(). These functions should take into account the current orientation of the title bar. - \o It is not possible to remove a title bar from a dock widget. However, + \li It is not possible to remove a title bar from a dock widget. However, a similar effect can be achieved by setting a default constructed QWidget as the title bar widget. \endlist diff --git a/src/widgets/widgets/qframe.cpp b/src/widgets/widgets/qframe.cpp index cae4137803..29c213f7af 100644 --- a/src/widgets/widgets/qframe.cpp +++ b/src/widgets/widgets/qframe.cpp @@ -97,15 +97,15 @@ inline void QFramePrivate::init() border: \l lineWidth, \l midLineWidth, and \l frameWidth. \list - \o The line width is the width of the frame border. It can be modified + \li The line width is the width of the frame border. It can be modified to customize the frame's appearance. - \o The mid-line width specifies the width of an extra line in the + \li The mid-line width specifies the width of an extra line in the middle of the frame, which uses a third color to obtain a special 3D effect. Notice that a mid-line is only drawn for \l Box, \l HLine and \l VLine frames that are raised or sunken. - \o The frame width is determined by the frame style, and the frameWidth() + \li The frame width is determined by the frame style, and the frameWidth() function is used to obtain the value defined for the style used. \endlist diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp index 17f3a9323a..cf3e14871f 100644 --- a/src/widgets/widgets/qgroupbox.cpp +++ b/src/widgets/widgets/qgroupbox.cpp @@ -172,12 +172,12 @@ void QGroupBoxPrivate::click() \snippet examples/widgets/groupbox/window.cpp 2 \table 100% - \row \o \inlineimage windowsxp-groupbox.png Screenshot of a Windows XP style group box - \o \inlineimage macintosh-groupbox.png Screenshot of a Macintosh style group box - \o \inlineimage plastique-groupbox.png Screenshot of a Plastique style group box - \row \o A \l{Windows XP Style Widget Gallery}{Windows XP style} group box. - \o A \l{Macintosh Style Widget Gallery}{Macintosh style} group box. - \o A \l{Plastique Style Widget Gallery}{Plastique style} group box. + \row \li \inlineimage windowsxp-groupbox.png Screenshot of a Windows XP style group box + \li \inlineimage macintosh-groupbox.png Screenshot of a Macintosh style group box + \li \inlineimage plastique-groupbox.png Screenshot of a Plastique style group box + \row \li A \l{Windows XP Style Widget Gallery}{Windows XP style} group box. + \li A \l{Macintosh Style Widget Gallery}{Macintosh style} group box. + \li A \l{Plastique Style Widget Gallery}{Plastique style} group box. \endtable \sa QButtonGroup, {Group Box Example} @@ -287,9 +287,9 @@ QString QGroupBox::title() const the following list: \list - \i Qt::AlignLeft aligns the title text with the left-hand side of the group box. - \i Qt::AlignRight aligns the title text with the right-hand side of the group box. - \i Qt::AlignHCenter aligns the title text with the horizontal center of the group box. + \li Qt::AlignLeft aligns the title text with the left-hand side of the group box. + \li Qt::AlignRight aligns the title text with the right-hand side of the group box. + \li Qt::AlignHCenter aligns the title text with the horizontal center of the group box. \endlist The default alignment is Qt::AlignLeft. @@ -516,7 +516,7 @@ QSize QGroupBox::minimumSizeHint() const By default, this property is disabled; i.e. group boxes are not flat unless explicitly specified. - \bold{Note:} In some styles, flat and non-flat group boxes have similar + \b{Note:} In some styles, flat and non-flat group boxes have similar representations and may not be as distinguishable as they are in other styles. diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp index d23fab4083..82e56f3354 100644 --- a/src/widgets/widgets/qlabel.cpp +++ b/src/widgets/widgets/qlabel.cpp @@ -76,20 +76,20 @@ QT_BEGIN_NAMESPACE A QLabel can contain any of the following content types: \table - \header \o Content \o Setting - \row \o Plain text - \o Pass a QString to setText(). - \row \o Rich text - \o Pass a QString that contains rich text to setText(). - \row \o A pixmap - \o Pass a QPixmap to setPixmap(). - \row \o A movie - \o Pass a QMovie to setMovie(). - \row \o A number - \o Pass an \e int or a \e double to setNum(), which converts + \header \li Content \li Setting + \row \li Plain text + \li Pass a QString to setText(). + \row \li Rich text + \li Pass a QString that contains rich text to setText(). + \row \li A pixmap + \li Pass a QPixmap to setPixmap(). + \row \li A movie + \li Pass a QMovie to setMovie(). + \row \li A number + \li Pass an \e int or a \e double to setNum(), which converts the number to plain text. - \row \o Nothing - \o The same as an empty plain text. This is the default. Set + \row \li Nothing + \li The same as an empty plain text. This is the default. Set by clear(). \endtable @@ -134,14 +134,14 @@ QT_BEGIN_NAMESPACE \table 100% \row - \o \inlineimage macintosh-label.png Screenshot of a Macintosh style label - \o A label shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \li \inlineimage macintosh-label.png Screenshot of a Macintosh style label + \li A label shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. \row - \o \inlineimage plastique-label.png Screenshot of a Plastique style label - \o A label shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \li \inlineimage plastique-label.png Screenshot of a Plastique style label + \li A label shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \row - \o \inlineimage windowsxp-label.png Screenshot of a Windows XP style label - \o A label shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \li \inlineimage windowsxp-label.png Screenshot of a Windows XP style label + \li A label shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. \endtable \sa QLineEdit, QTextEdit, QPixmap, QMovie, @@ -655,7 +655,7 @@ int QLabel::heightForWidth(int w) const QDesktopServices::openUrl() instead of emitting the linkActivated() signal. - \bold{Note:} The textInteractionFlags set on the label need to include + \b{Note:} The textInteractionFlags set on the label need to include either LinksAccessibleByMouse or LinksAccessibleByKeyboard. The default value is false. @@ -723,7 +723,7 @@ Qt::TextInteractionFlags QLabel::textInteractionFlags() const \sa selectedText() - \bold{Note:} The textInteractionFlags set on the label need to include + \b{Note:} The textInteractionFlags set on the label need to include either TextSelectableByMouse or TextSelectableByKeyboard. \since 4.7 @@ -751,7 +751,7 @@ void QLabel::setSelection(int start, int length) \sa selectedText() - \bold{Note:} The textInteractionFlags set on the label need to include + \b{Note:} The textInteractionFlags set on the label need to include either TextSelectableByMouse or TextSelectableByKeyboard. \since 4.7 @@ -775,7 +775,7 @@ bool QLabel::hasSelectedText() const \sa hasSelectedText() - \bold{Note:} The textInteractionFlags set on the label need to include + \b{Note:} The textInteractionFlags set on the label need to include either TextSelectableByMouse or TextSelectableByKeyboard. \since 4.7 @@ -794,7 +794,7 @@ QString QLabel::selectedText() const \sa selectedText() - \bold{Note:} The textInteractionFlags set on the label need to include + \b{Note:} The textInteractionFlags set on the label need to include either TextSelectableByMouse or TextSelectableByKeyboard. \since 4.7 diff --git a/src/widgets/widgets/qlcdnumber.cpp b/src/widgets/widgets/qlcdnumber.cpp index 71e08fdaeb..4639b15834 100644 --- a/src/widgets/widgets/qlcdnumber.cpp +++ b/src/widgets/widgets/qlcdnumber.cpp @@ -108,13 +108,13 @@ public: Sinclair Spectrum\endlink. \table - \row \o \inlineimage motif-lcdnumber.png Screenshot of a Motif style LCD number widget + \row \li \inlineimage motif-lcdnumber.png Screenshot of a Motif style LCD number widget \inlineimage cde-lcdnumber.png Screenshot of a CDE style LCD number widget \inlineimage windows-lcdnumber.png Screenshot of a Windows style LCD number widget \inlineimage windowsxp-lcdnumber.png Screenshot of a Windows XP style LCD number widget \inlineimage macintosh-lcdnumber.png Screenshot of a Macintosh style LCD number widget \inlineimage plastique-lcdnumber.png Screenshot of a Plastique style LCD number widget - \row \o LCD number widgets shown in various widget styles (from left to right): + \row \li LCD number widgets shown in various widget styles (from left to right): \l{Motif Style Widget Gallery}{Motif}, \l{CDE Style Widget Gallery}{CDE}, \l{Windows Style Widget Gallery}{Windows}, \l{Windows XP Style Widget Gallery}{Windows XP}, \l{Macintosh Style Widget Gallery}{Macintosh}, \l{Plastique Style Widget Gallery}{Plastique}. @@ -1184,14 +1184,14 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter \brief the style of the LCDNumber \table - \header \i Style \i Result - \row \i \c Outline - \i Produces raised segments filled with the background color - \row \i \c Filled + \header \li Style \li Result + \row \li \c Outline + \li Produces raised segments filled with the background color + \row \li \c Filled (this is the default). - \i Produces raised segments filled with the foreground color. - \row \i \c Flat - \i Produces flat segments filled with the foreground color. + \li Produces raised segments filled with the foreground color. + \row \li \c Flat + \li Produces flat segments filled with the foreground color. \endtable \c Outline and \c Filled will additionally use diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 7118881ef2..07843136ff 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -177,39 +177,39 @@ void QLineEdit::initStyleOption(QStyleOptionFrame *option) const that presents some of these editing options. \target desc \table - \header \i Keypress \i Action - \row \i Left Arrow \i Moves the cursor one character to the left. - \row \i Shift+Left Arrow \i Moves and selects text one character to the left. - \row \i Right Arrow \i Moves the cursor one character to the right. - \row \i Shift+Right Arrow \i Moves and selects text one character to the right. - \row \i Home \i Moves the cursor to the beginning of the line. - \row \i End \i Moves the cursor to the end of the line. - \row \i Backspace \i Deletes the character to the left of the cursor. - \row \i Ctrl+Backspace \i Deletes the word to the left of the cursor. - \row \i Delete \i Deletes the character to the right of the cursor. - \row \i Ctrl+Delete \i Deletes the word to the right of the cursor. - \row \i Ctrl+A \i Select all. - \row \i Ctrl+C \i Copies the selected text to the clipboard. - \row \i Ctrl+Insert \i Copies the selected text to the clipboard. - \row \i Ctrl+K \i Deletes to the end of the line. - \row \i Ctrl+V \i Pastes the clipboard text into line edit. - \row \i Shift+Insert \i Pastes the clipboard text into line edit. - \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard. - \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard. - \row \i Ctrl+Z \i Undoes the last operation. - \row \i Ctrl+Y \i Redoes the last undone operation. + \header \li Keypress \li Action + \row \li Left Arrow \li Moves the cursor one character to the left. + \row \li Shift+Left Arrow \li Moves and selects text one character to the left. + \row \li Right Arrow \li Moves the cursor one character to the right. + \row \li Shift+Right Arrow \li Moves and selects text one character to the right. + \row \li Home \li Moves the cursor to the beginning of the line. + \row \li End \li Moves the cursor to the end of the line. + \row \li Backspace \li Deletes the character to the left of the cursor. + \row \li Ctrl+Backspace \li Deletes the word to the left of the cursor. + \row \li Delete \li Deletes the character to the right of the cursor. + \row \li Ctrl+Delete \li Deletes the word to the right of the cursor. + \row \li Ctrl+A \li Select all. + \row \li Ctrl+C \li Copies the selected text to the clipboard. + \row \li Ctrl+Insert \li Copies the selected text to the clipboard. + \row \li Ctrl+K \li Deletes to the end of the line. + \row \li Ctrl+V \li Pastes the clipboard text into line edit. + \row \li Shift+Insert \li Pastes the clipboard text into line edit. + \row \li Ctrl+X \li Deletes the selected text and copies it to the clipboard. + \row \li Shift+Delete \li Deletes the selected text and copies it to the clipboard. + \row \li Ctrl+Z \li Undoes the last operation. + \row \li Ctrl+Y \li Redoes the last undone operation. \endtable Any other key sequence that represents a valid character, will cause the character to be inserted into the line edit. \table 100% - \row \o \inlineimage macintosh-lineedit.png Screenshot of a Macintosh style line edit - \o A line edit shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage windows-lineedit.png Screenshot of a Windows XP style line edit - \o A line edit shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-lineedit.png Screenshot of a Plastique style line edit - \o A line edit shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage macintosh-lineedit.png Screenshot of a Macintosh style line edit + \li A line edit shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage windows-lineedit.png Screenshot of a Windows XP style line edit + \li A line edit shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage plastique-lineedit.png Screenshot of a Plastique style line edit + \li A line edit shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QTextEdit, QLabel, QComboBox, {fowler}{GUI Design Handbook: Field, Entry}, {Line Edits Example} @@ -1096,26 +1096,26 @@ QMargins QLineEdit::textMargins() const where a character is \e{permitted but not required}. \table - \header \i Character \i Meaning - \row \i \c A \i ASCII alphabetic character required. A-Z, a-z. - \row \i \c a \i ASCII alphabetic character permitted but not required. - \row \i \c N \i ASCII alphanumeric character required. A-Z, a-z, 0-9. - \row \i \c n \i ASCII alphanumeric character permitted but not required. - \row \i \c X \i Any character required. - \row \i \c x \i Any character permitted but not required. - \row \i \c 9 \i ASCII digit required. 0-9. - \row \i \c 0 \i ASCII digit permitted but not required. - \row \i \c D \i ASCII digit required. 1-9. - \row \i \c d \i ASCII digit permitted but not required (1-9). - \row \i \c # \i ASCII digit or plus/minus sign permitted but not required. - \row \i \c H \i Hexadecimal character required. A-F, a-f, 0-9. - \row \i \c h \i Hexadecimal character permitted but not required. - \row \i \c B \i Binary character required. 0-1. - \row \i \c b \i Binary character permitted but not required. - \row \i \c > \i All following alphabetic characters are uppercased. - \row \i \c < \i All following alphabetic characters are lowercased. - \row \i \c ! \i Switch off case conversion. - \row \i \tt{\\} \i Use \tt{\\} to escape the special + \header \li Character \li Meaning + \row \li \c A \li ASCII alphabetic character required. A-Z, a-z. + \row \li \c a \li ASCII alphabetic character permitted but not required. + \row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9. + \row \li \c n \li ASCII alphanumeric character permitted but not required. + \row \li \c X \li Any character required. + \row \li \c x \li Any character permitted but not required. + \row \li \c 9 \li ASCII digit required. 0-9. + \row \li \c 0 \li ASCII digit permitted but not required. + \row \li \c D \li ASCII digit required. 1-9. + \row \li \c d \li ASCII digit permitted but not required (1-9). + \row \li \c # \li ASCII digit or plus/minus sign permitted but not required. + \row \li \c H \li Hexadecimal character required. A-F, a-f, 0-9. + \row \li \c h \li Hexadecimal character permitted but not required. + \row \li \c B \li Binary character required. 0-1. + \row \li \c b \li Binary character permitted but not required. + \row \li \c > \li All following alphabetic characters are uppercased. + \row \li \c < \li All following alphabetic characters are lowercased. + \row \li \c ! \li Switch off case conversion. + \row \li \tt{\\} \li Use \tt{\\} to escape the special characters listed above to use them as separators. \endtable @@ -1127,11 +1127,11 @@ QMargins QLineEdit::textMargins() const Examples: \table - \header \i Mask \i Notes - \row \i \c 000.000.000.000;_ \i IP address; blanks are \c{_}. - \row \i \c HH:HH:HH:HH:HH:HH;_ \i MAC address - \row \i \c 0000-00-00 \i ISO Date; blanks are \c space - \row \i \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \i License number; + \header \li Mask \li Notes + \row \li \c 000.000.000.000;_ \li IP address; blanks are \c{_}. + \row \li \c HH:HH:HH:HH:HH:HH;_ \li MAC address + \row \li \c 0000-00-00 \li ISO Date; blanks are \c space + \row \li \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \li License number; blanks are \c - and all (alphabetic) characters are converted to uppercase. \endtable diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 73ba0cc15e..7607f2f238 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -1480,12 +1480,12 @@ bool QMainWindow::event(QEvent *event) moved to that. This means a couple of things. \list - \i QToolBars in this toolbar area are not movable and you cannot drag other + \li QToolBars in this toolbar area are not movable and you cannot drag other toolbars to it - \i Toolbar breaks are not respected or preserved - \i Any custom widgets in the toolbar will not be shown if the toolbar + \li Toolbar breaks are not respected or preserved + \li Any custom widgets in the toolbar will not be shown if the toolbar becomes too small (only actions will be shown) - \i Before Qt 4.5, if you called showFullScreen() on the main window, the QToolbar would + \li Before Qt 4.5, if you called showFullScreen() on the main window, the QToolbar would disappear since it is considered to be part of the title bar. Qt 4.5 and up will now work around this by pulling the toolbars out and back into the regular toolbar and vice versa when you swap out. \endlist diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 7d73a66c5c..36fba72963 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -92,8 +92,8 @@ slots and are easily connected to menu entries. \table - \row \o \inlineimage mdi-cascade.png - \o \inlineimage mdi-tile.png + \row \li \inlineimage mdi-cascade.png + \li \inlineimage mdi-tile.png \endtable \note The default scroll bar property for QMdiArea is Qt::ScrollBarAlwaysOff. diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 7ebfdbecae..3fb2a6122c 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -1218,9 +1218,9 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) \table 100% \row - \o \inlineimage plastique-menu.png - \o \inlineimage windowsxp-menu.png - \o \inlineimage macintosh-menu.png + \li \inlineimage plastique-menu.png + \li \inlineimage windowsxp-menu.png + \li \inlineimage macintosh-menu.png \endtable \caption Fig. A menu shown in \l{Plastique Style Widget Gallery}{Plastique widget style}, \l{Windows XP Style Widget Gallery}{Windows XP widget style}, @@ -1284,7 +1284,7 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) See the \l{mainwindows/menus}{Menus} example for an example of how to use QMenuBar and QMenu in your application. - \bold{Important inherited functions:} addAction(), removeAction(), clear(), + \b{Important inherited functions:} addAction(), removeAction(), clear(), addSeparator(), and addMenu(). \sa QMenuBar, {fowler}{GUI Design Handbook: Menu, Drop-Down and Pop-Up}, diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 16e486e77f..11f6592cc9 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -621,17 +621,17 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti \table - \row \o \inlineimage plastique-menubar.png A menu bar shown in the + \row \li \inlineimage plastique-menubar.png A menu bar shown in the Plastique widget style. - \o The \l{QPlastiqueStyle}{Plastique widget style}, like most + \li The \l{QPlastiqueStyle}{Plastique widget style}, like most other styles, handles the \gui{Help} menu in the same way as it handles any other menu. - \row \o \inlineimage motif-menubar.png A menu bar shown in the + \row \li \inlineimage motif-menubar.png A menu bar shown in the Motif widget style. - \o The \l{QMotifStyle}{Motif widget style} treats \gui{Help} menus + \li The \l{QMotifStyle}{Motif widget style} treats \gui{Help} menus in a special way, placing them at right-hand end of the menu bar. \endtable @@ -652,18 +652,18 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti the strings looked for and where the entry is placed if matched: \table - \header \i String matches \i Placement \i Notes - \row \i about.* - \i Application Menu | About - \i The application name is fetched from the \c {Info.plist} file + \header \li String matches \li Placement \li Notes + \row \li about.* + \li Application Menu | About + \li The application name is fetched from the \c {Info.plist} file (see note below). If this entry is not found no About item will appear in the Application Menu. - \row \i config, options, setup, settings or preferences - \i Application Menu | Preferences - \i If this entry is not found the Settings item will be disabled - \row \i quit or exit - \i Application Menu | Quit - \i If this entry is not found a default Quit item will be + \row \li config, options, setup, settings or preferences + \li Application Menu | Preferences + \li If this entry is not found the Settings item will be disabled + \row \li quit or exit + \li Application Menu | Quit + \li If this entry is not found a default Quit item will be created to call QApplication::quit() \endtable @@ -676,12 +676,12 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti \snippet doc/src/snippets/code/src_gui_widgets_qmenubar.cpp 1 - \bold{Note:} Do \e{not} call QMainWindow::menuBar() to create the + \b{Note:} Do \e{not} call QMainWindow::menuBar() to create the shared menu bar, because that menu bar will have the QMainWindow as its parent. That menu bar would only be displayed for the parent QMainWindow. - \bold{Note:} The text used for the application name in the menu + \b{Note:} The text used for the application name in the menu bar is obtained from the value set in the \c{Info.plist} file in the application's bundle. See \l{Deploying an Application on Mac OS X} for more information. diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index de6cb6a283..fad2d4e747 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -1081,19 +1081,19 @@ void QPlainTextEditPrivate::ensureViewportLayouted() When QPlainTextEdit is used read-only the key bindings are limited to navigation, and text may only be selected with the mouse: \table - \header \i Keypresses \i Action - \row \i Qt::UpArrow \i Moves one line up. - \row \i Qt::DownArrow \i Moves one line down. - \row \i Qt::LeftArrow \i Moves one character to the left. - \row \i Qt::RightArrow \i Moves one character to the right. - \row \i PageUp \i Moves one (viewport) page up. - \row \i PageDown \i Moves one (viewport) page down. - \row \i Home \i Moves to the beginning of the text. - \row \i End \i Moves to the end of the text. - \row \i Alt+Wheel - \i Scrolls the page horizontally (the Wheel is the mouse wheel). - \row \i Ctrl+Wheel \i Zooms the text. - \row \i Ctrl+A \i Selects all text. + \header \li Keypresses \li Action + \row \li Qt::UpArrow \li Moves one line up. + \row \li Qt::DownArrow \li Moves one line down. + \row \li Qt::LeftArrow \li Moves one character to the left. + \row \li Qt::RightArrow \li Moves one character to the right. + \row \li PageUp \li Moves one (viewport) page up. + \row \li PageDown \li Moves one (viewport) page down. + \row \li Home \li Moves to the beginning of the text. + \row \li End \li Moves to the end of the text. + \row \li Alt+Wheel + \li Scrolls the page horizontally (the Wheel is the mouse wheel). + \row \li Ctrl+Wheel \li Zooms the text. + \row \li Ctrl+A \li Selects all text. \endtable @@ -1127,34 +1127,34 @@ void QPlainTextEditPrivate::ensureViewportLayouted() The list of key bindings which are implemented for editing: \table - \header \i Keypresses \i Action - \row \i Backspace \i Deletes the character to the left of the cursor. - \row \i Delete \i Deletes the character to the right of the cursor. - \row \i Ctrl+C \i Copy the selected text to the clipboard. - \row \i Ctrl+Insert \i Copy the selected text to the clipboard. - \row \i Ctrl+K \i Deletes to the end of the line. - \row \i Ctrl+V \i Pastes the clipboard text into text edit. - \row \i Shift+Insert \i Pastes the clipboard text into text edit. - \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard. - \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard. - \row \i Ctrl+Z \i Undoes the last operation. - \row \i Ctrl+Y \i Redoes the last operation. - \row \i LeftArrow \i Moves the cursor one character to the left. - \row \i Ctrl+LeftArrow \i Moves the cursor one word to the left. - \row \i RightArrow \i Moves the cursor one character to the right. - \row \i Ctrl+RightArrow \i Moves the cursor one word to the right. - \row \i UpArrow \i Moves the cursor one line up. - \row \i Ctrl+UpArrow \i Moves the cursor one word up. - \row \i DownArrow \i Moves the cursor one line down. - \row \i Ctrl+Down Arrow \i Moves the cursor one word down. - \row \i PageUp \i Moves the cursor one page up. - \row \i PageDown \i Moves the cursor one page down. - \row \i Home \i Moves the cursor to the beginning of the line. - \row \i Ctrl+Home \i Moves the cursor to the beginning of the text. - \row \i End \i Moves the cursor to the end of the line. - \row \i Ctrl+End \i Moves the cursor to the end of the text. - \row \i Alt+Wheel \i Scrolls the page horizontally (the Wheel is the mouse wheel). - \row \i Ctrl+Wheel \i Zooms the text. + \header \li Keypresses \li Action + \row \li Backspace \li Deletes the character to the left of the cursor. + \row \li Delete \li Deletes the character to the right of the cursor. + \row \li Ctrl+C \li Copy the selected text to the clipboard. + \row \li Ctrl+Insert \li Copy the selected text to the clipboard. + \row \li Ctrl+K \li Deletes to the end of the line. + \row \li Ctrl+V \li Pastes the clipboard text into text edit. + \row \li Shift+Insert \li Pastes the clipboard text into text edit. + \row \li Ctrl+X \li Deletes the selected text and copies it to the clipboard. + \row \li Shift+Delete \li Deletes the selected text and copies it to the clipboard. + \row \li Ctrl+Z \li Undoes the last operation. + \row \li Ctrl+Y \li Redoes the last operation. + \row \li LeftArrow \li Moves the cursor one character to the left. + \row \li Ctrl+LeftArrow \li Moves the cursor one word to the left. + \row \li RightArrow \li Moves the cursor one character to the right. + \row \li Ctrl+RightArrow \li Moves the cursor one word to the right. + \row \li UpArrow \li Moves the cursor one line up. + \row \li Ctrl+UpArrow \li Moves the cursor one word up. + \row \li DownArrow \li Moves the cursor one line down. + \row \li Ctrl+Down Arrow \li Moves the cursor one word down. + \row \li PageUp \li Moves the cursor one page up. + \row \li PageDown \li Moves the cursor one page down. + \row \li Home \li Moves the cursor to the beginning of the line. + \row \li Ctrl+Home \li Moves the cursor to the beginning of the text. + \row \li End \li Moves the cursor to the end of the line. + \row \li Ctrl+End \li Moves the cursor to the end of the text. + \row \li Alt+Wheel \li Scrolls the page horizontally (the Wheel is the mouse wheel). + \row \li Ctrl+Wheel \li Zooms the text. \endtable To select (mark) text hold down the Shift key whilst pressing one diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index eabed2ee62..816b847cf5 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -196,12 +196,12 @@ bool QProgressBarPrivate::repaintRequired() const they are unable to determine the size of the item being downloaded. \table - \row \o \inlineimage macintosh-progressbar.png Screenshot of a Macintosh style progress bar - \o A progress bar shown in the Macintosh widget style. - \row \o \inlineimage windowsxp-progressbar.png Screenshot of a Windows XP style progress bar - \o A progress bar shown in the Windows XP widget style. - \row \o \inlineimage plastique-progressbar.png Screenshot of a Plastique style progress bar - \o A progress bar shown in the Plastique widget style. + \row \li \inlineimage macintosh-progressbar.png Screenshot of a Macintosh style progress bar + \li A progress bar shown in the Macintosh widget style. + \row \li \inlineimage windowsxp-progressbar.png Screenshot of a Windows XP style progress bar + \li A progress bar shown in the Windows XP widget style. + \row \li \inlineimage plastique-progressbar.png Screenshot of a Plastique style progress bar + \li A progress bar shown in the Plastique widget style. \endtable \sa QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator} diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp index 99252c43dc..7ca5dcb486 100644 --- a/src/widgets/widgets/qpushbutton.cpp +++ b/src/widgets/widgets/qpushbutton.cpp @@ -126,13 +126,13 @@ QT_BEGIN_NAMESPACE The most important modes or states are: \list - \i Available or not (grayed out, disabled). - \i Standard push button, toggling push button or menu button. - \i On or off (only for toggling push buttons). - \i Default or normal. The default button in a dialog can generally + \li Available or not (grayed out, disabled). + \li Standard push button, toggling push button or menu button. + \li On or off (only for toggling push buttons). + \li Default or normal. The default button in a dialog can generally be "clicked" using the Enter or Return key. - \i Auto-repeat or not. - \i Pressed down or not. + \li Auto-repeat or not. + \li Pressed down or not. \endlist As a general rule, use a push button when the application or @@ -160,18 +160,18 @@ QT_BEGIN_NAMESPACE check boxes (see QCheckBox). \table 100% - \row \o \inlineimage macintosh-pushbutton.png Screenshot of a Macintosh style push button - \o A push button shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage macintosh-pushbutton.png Screenshot of a Macintosh style push button + \li A push button shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. Note that when a button's width becomes smaller than 50 or its height becomes smaller than 30, the button's corners are changed from round to square. Use the setMinimumSize() function to prevent this behavior. - \row \o \inlineimage windowsxp-pushbutton.png Screenshot of a Windows XP style push button - \o A push button shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-pushbutton.png Screenshot of a Plastique style push button - \o A push button shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage windowsxp-pushbutton.png Screenshot of a Windows XP style push button + \li A push button shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage plastique-pushbutton.png Screenshot of a Plastique style push button + \li A push button shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable In Qt, the QAbstractButton base class provides most of the modes @@ -518,9 +518,9 @@ void QPushButton::focusOutEvent(QFocusEvent *e) \table 100% \row - \o \inlineimage plastique-pushbutton-menu.png Screenshot of a Plastique style push button with popup menu. - \o \inlineimage cleanlooks-pushbutton-menu.png Screenshot of a Cleanlooks style push button with popup menu. - \o Push buttons with popup menus shown in the \l{Plastique Style Widget Gallery}{Plastique widget style} + \li \inlineimage plastique-pushbutton-menu.png Screenshot of a Plastique style push button with popup menu. + \li \inlineimage cleanlooks-pushbutton-menu.png Screenshot of a Cleanlooks style push button with popup menu. + \li Push buttons with popup menus shown in the \l{Plastique Style Widget Gallery}{Plastique widget style} (left) and \l{Cleanlooks Style Widget Gallery}{Cleanlooks widget style} (right). \endtable diff --git a/src/widgets/widgets/qradiobutton.cpp b/src/widgets/widgets/qradiobutton.cpp index 792550949b..11cd89bca2 100644 --- a/src/widgets/widgets/qradiobutton.cpp +++ b/src/widgets/widgets/qradiobutton.cpp @@ -116,12 +116,12 @@ void QRadioButtonPrivate::init() toggle(), pressed(), released(), clicked(), and toggled(). \table 100% - \row \o \inlineimage plastique-radiobutton.png Screenshot of a Plastique radio button - \o A radio button shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. - \row \o \inlineimage windows-radiobutton.png Screenshot of a Windows XP radio button - \o A radio button shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage macintosh-radiobutton.png Screenshot of a Macintosh radio button - \o A radio button shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage plastique-radiobutton.png Screenshot of a Plastique radio button + \li A radio button shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage windows-radiobutton.png Screenshot of a Windows XP radio button + \li A radio button shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage macintosh-radiobutton.png Screenshot of a Macintosh radio button + \li A radio button shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. \endtable \sa QPushButton, QToolButton, QCheckBox, {fowler}{GUI Design Handbook: Radio Button}, diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp index 490dea0d2d..84be2d569b 100644 --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -77,9 +77,9 @@ QT_BEGIN_NAMESPACE \table \row - \o \inlineimage qscrollarea-noscrollbars.png - \o \inlineimage qscrollarea-onescrollbar.png - \o \inlineimage qscrollarea-twoscrollbars.png + \li \inlineimage qscrollarea-noscrollbars.png + \li \inlineimage qscrollarea-onescrollbar.png + \li \inlineimage qscrollarea-twoscrollbars.png \endtable The scroll bars appearance depends on the currently set \l diff --git a/src/widgets/widgets/qscrollbar.cpp b/src/widgets/widgets/qscrollbar.cpp index cb3126e566..6ac5473f2e 100644 --- a/src/widgets/widgets/qscrollbar.cpp +++ b/src/widgets/widgets/qscrollbar.cpp @@ -83,21 +83,21 @@ QT_BEGIN_NAMESPACE needs. \table - \row \o \image qscrollbar-picture.png - \o Scroll bars typically include four separate controls: a slider, + \row \li \image qscrollbar-picture.png + \li Scroll bars typically include four separate controls: a slider, scroll arrows, and a page control. \list - \o a. The slider provides a way to quickly go to any part of the + \li a. The slider provides a way to quickly go to any part of the document, but does not support accurate navigation within large documents. - \o b. The scroll arrows are push buttons which can be used to accurately + \li b. The scroll arrows are push buttons which can be used to accurately navigate to a particular place in a document. For a vertical scroll bar connected to a text editor, these typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. In editors and list boxes a "line" might mean one line of text; in an image viewer it might mean 20 pixels. - \o c. The page control is the area over which the slider is dragged (the + \li c. The page control is the area over which the slider is dragged (the scroll bar's background). Clicking here moves the scroll bar towards the click by one "page". This value is usually the same as the length of the slider. @@ -135,8 +135,8 @@ QT_BEGIN_NAMESPACE value of 80. This would give us a scroll bar with five "pages". \table - \row \o \inlineimage qscrollbar-values.png - \o The relationship between a document length, the range of values used + \row \li \inlineimage qscrollbar-values.png + \li The relationship between a document length, the range of values used in a scroll bar, and the page step is simple in many common situations. The scroll bar's range of values is determined by subtracting a chosen page step from some value representing the length of the document. @@ -153,18 +153,18 @@ QT_BEGIN_NAMESPACE ScrollBar inherits a comprehensive set of signals from QAbstractSlider: \list - \o \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the + \li \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the scroll bar's value has changed. The tracking() determines whether this signal is emitted during user interaction. - \o \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the + \li \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the scroll bar's range of values has changed. - \o \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when + \li \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when the user starts to drag the slider. - \o \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user + \li \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user drags the slider. - \o \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when + \li \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when the user releases the slider. - \o \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted + \li \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted when the scroll bar is changed by user interaction or via the \l{QAbstractSlider::triggerAction()}{triggerAction()} function. \endlist @@ -173,12 +173,12 @@ QT_BEGIN_NAMESPACE default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to enable keyboard interaction with the scroll bar: \list - \o Left/Right move a horizontal scroll bar by one single step. - \o Up/Down move a vertical scroll bar by one single step. - \o PageUp moves up one page. - \o PageDown moves down one page. - \o Home moves to the start (mininum). - \o End moves to the end (maximum). + \li Left/Right move a horizontal scroll bar by one single step. + \li Up/Down move a vertical scroll bar by one single step. + \li PageUp moves up one page. + \li PageDown moves down one page. + \li Home moves to the start (mininum). + \li End moves to the end (maximum). \endlist The slider itself can be controlled by using the @@ -190,12 +190,12 @@ QT_BEGIN_NAMESPACE slider. \table 100% - \row \o \inlineimage macintosh-horizontalscrollbar.png Screenshot of a Macintosh style scroll bar - \o A scroll bar shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage windowsxp-horizontalscrollbar.png Screenshot of a Windows XP style scroll bar - \o A scroll bar shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-horizontalscrollbar.png Screenshot of a Plastique style scroll bar - \o A scroll bar shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage macintosh-horizontalscrollbar.png Screenshot of a Macintosh style scroll bar + \li A scroll bar shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage windowsxp-horizontalscrollbar.png Screenshot of a Windows XP style scroll bar + \li A scroll bar shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage plastique-horizontalscrollbar.png Screenshot of a Plastique style scroll bar + \li A scroll bar shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QScrollArea, QSlider, QDial, QSpinBox, {fowler}{GUI Design Handbook: Scroll Bar}, {Sliders Example} diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp index 09557a3c90..4a5269c110 100644 --- a/src/widgets/widgets/qsizegrip.cpp +++ b/src/widgets/widgets/qsizegrip.cpp @@ -195,8 +195,8 @@ Qt::Corner QSizeGripPrivate::corner() const window is shown full screen or maximised. \table 50% - \row \o \inlineimage plastique-sizegrip.png Screenshot of a Plastique style size grip - \o A size grip widget at the bottom-right corner of a main window, shown in the + \row \li \inlineimage plastique-sizegrip.png Screenshot of a Plastique style size grip + \li A size grip widget at the bottom-right corner of a main window, shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable diff --git a/src/widgets/widgets/qslider.cpp b/src/widgets/widgets/qslider.cpp index b05726c965..7f77bc9d03 100644 --- a/src/widgets/widgets/qslider.cpp +++ b/src/widgets/widgets/qslider.cpp @@ -225,17 +225,17 @@ QStyle::SubControl QSliderPrivate::newHoverControl(const QPoint &pos) QSlider inherits a comprehensive set of signals: \table - \header \o Signal \o Description - \row \o \l valueChanged() - \o Emitted when the slider's value has changed. The tracking() + \header \li Signal \li Description + \row \li \l valueChanged() + \li Emitted when the slider's value has changed. The tracking() determines whether this signal is emitted during user interaction. - \row \o \l sliderPressed() - \o Emitted when the user starts to drag the slider. - \row \o \l sliderMoved() - \o Emitted when the user drags the slider. - \row \o \l sliderReleased() - \o Emitted when the user releases the slider. + \row \li \l sliderPressed() + \li Emitted when the user starts to drag the slider. + \row \li \l sliderMoved() + \li Emitted when the user drags the slider. + \row \li \l sliderReleased() + \li Emitted when the user releases the slider. \endtable QSlider only provides integer ranges. Note that although @@ -246,21 +246,21 @@ QStyle::SubControl QSliderPrivate::newHoverControl(const QPoint &pos) keyboard interface. The keyboard interface is the following: \list - \o Left/Right move a horizontal slider by one single step. - \o Up/Down move a vertical slider by one single step. - \o PageUp moves up one page. - \o PageDown moves down one page. - \o Home moves to the start (mininum). - \o End moves to the end (maximum). + \li Left/Right move a horizontal slider by one single step. + \li Up/Down move a vertical slider by one single step. + \li PageUp moves up one page. + \li PageDown moves down one page. + \li Home moves to the start (mininum). + \li End moves to the end (maximum). \endlist \table 100% - \row \o \inlineimage macintosh-slider.png Screenshot of a Macintosh slider - \o A slider shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. - \row \o \inlineimage windows-slider.png Screenshot of a Windows XP slider - \o A slider shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-slider.png Screenshot of a Plastique slider - \o A slider shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage macintosh-slider.png Screenshot of a Macintosh slider + \li A slider shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage windows-slider.png Screenshot of a Windows XP slider + \li A slider shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage plastique-slider.png Screenshot of a Plastique slider + \li A slider shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. \endtable \sa QScrollBar, QSpinBox, QDial, {fowler}{GUI Design Handbook: Slider}, {Sliders Example} diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 3038d8e30c..7dcaead2f4 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -152,12 +152,12 @@ public: setSpecialValueText() for how to do this with QSpinBox. \table 100% - \row \o \inlineimage windowsxp-spinbox.png Screenshot of a Windows XP spin box - \o A spin box shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. - \row \o \inlineimage plastique-spinbox.png Screenshot of a Plastique spin box - \o A spin box shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. - \row \o \inlineimage macintosh-spinbox.png Screenshot of a Macintosh spin box - \o A spin box shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. + \row \li \inlineimage windowsxp-spinbox.png Screenshot of a Windows XP spin box + \li A spin box shown in the \l{Windows XP Style Widget Gallery}{Windows XP widget style}. + \row \li \inlineimage plastique-spinbox.png Screenshot of a Plastique spin box + \li A spin box shown in the \l{Plastique Style Widget Gallery}{Plastique widget style}. + \row \li \inlineimage macintosh-spinbox.png Screenshot of a Macintosh spin box + \li A spin box shown in the \l{Macintosh Style Widget Gallery}{Macintosh widget style}. \endtable \section1 Subclassing QSpinBox diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp index 5a8a382a58..9617d6de58 100644 --- a/src/widgets/widgets/qstackedwidget.cpp +++ b/src/widgets/widgets/qstackedwidget.cpp @@ -232,7 +232,7 @@ int QStackedWidget::insertWidget(int index, QWidget *widget) not deleted but simply removed from the stacked layout, causing it to be hidden. - \bold{Note:} Ownership of \a widget reverts to the application. + \b{Note:} Ownership of \a widget reverts to the application. \sa addWidget(), insertWidget(), currentWidget() */ diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp index 9f170626da..4b9242499c 100644 --- a/src/widgets/widgets/qstatusbar.cpp +++ b/src/widgets/widgets/qstatusbar.cpp @@ -165,12 +165,12 @@ QRect QStatusBarPrivate::messageRect() const Each status indicator falls into one of three categories: \list - \o \e Temporary - briefly occupies most of the status bar. Used + \li \e Temporary - briefly occupies most of the status bar. Used to explain tool tip texts or menu entries, for example. - \o \e Normal - occupies part of the status bar and may be hidden + \li \e Normal - occupies part of the status bar and may be hidden by temporary messages. Used to display the page and line number in a word processor, for example. - \o \e Permanent - is never hidden. Used for important mode + \li \e Permanent - is never hidden. Used for important mode indications, for example, some applications put a Caps Lock indicator in the status bar. \endlist diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index 580aea10b9..ca94854d11 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -252,21 +252,21 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const tab: \list - \i tabSizeHint() calcuates the size of a tab. - \i tabInserted() notifies that a new tab was added. - \i tabRemoved() notifies that a tab was removed. - \i tabLayoutChange() notifies that the tabs have been re-laid out. - \i paintEvent() paints all tabs. + \li tabSizeHint() calcuates the size of a tab. + \li tabInserted() notifies that a new tab was added. + \li tabRemoved() notifies that a tab was removed. + \li tabLayoutChange() notifies that the tabs have been re-laid out. + \li paintEvent() paints all tabs. \endlist For subclasses, you might also need the tabRect() functions which returns the visual geometry of a single tab. \table 100% - \row \o \inlineimage plastique-tabbar.png Screenshot of a Plastique style tab bar - \o A tab bar shown in the Plastique widget style. - \row \o \inlineimage plastique-tabbar-truncated.png Screenshot of a truncated Plastique tab bar - \o A truncated tab bar shown in the Plastique widget style. + \row \li \inlineimage plastique-tabbar.png Screenshot of a Plastique style tab bar + \li A tab bar shown in the Plastique widget style. + \row \li \inlineimage plastique-tabbar-truncated.png Screenshot of a truncated Plastique tab bar + \li A truncated tab bar shown in the Plastique widget style. \endtable \sa QTabWidget diff --git a/src/widgets/widgets/qtabwidget.cpp b/src/widgets/widgets/qtabwidget.cpp index 612d51826c..505287512e 100644 --- a/src/widgets/widgets/qtabwidget.cpp +++ b/src/widgets/widgets/qtabwidget.cpp @@ -77,12 +77,12 @@ QT_BEGIN_NAMESPACE The normal way to use QTabWidget is to do the following: \list 1 - \i Create a QTabWidget. - \i Create a QWidget for each of the pages in the tab dialog, but + \li Create a QTabWidget. + \li Create a QWidget for each of the pages in the tab dialog, but do not specify parent widgets for them. - \i Insert child widgets into the page widget, using layouts to + \li Insert child widgets into the page widget, using layouts to position them as normal. - \i Call addTab() or insertTab() to put the page widgets into the + \li Call addTab() or insertTab() to put the page widgets into the tab widget, giving each tab a suitable label with an optional keyboard shortcut. \endlist @@ -120,12 +120,12 @@ QT_BEGIN_NAMESPACE area, organizing the individual pages). \table 100% - \row \o \inlineimage windowsxp-tabwidget.png Screenshot of a Windows XP style tab widget - \o \inlineimage macintosh-tabwidget.png Screenshot of a Macintosh style tab widget - \o \inlineimage plastique-tabwidget.png Screenshot of a Plastique style tab widget - \row \o A Windows XP style tab widget. - \o A Macintosh style tab widget. - \o A Plastique style tab widget. + \row \li \inlineimage windowsxp-tabwidget.png Screenshot of a Windows XP style tab widget + \li \inlineimage macintosh-tabwidget.png Screenshot of a Macintosh style tab widget + \li \inlineimage plastique-tabwidget.png Screenshot of a Plastique style tab widget + \row \li A Windows XP style tab widget. + \li A Macintosh style tab widget. + \li A Plastique style tab widget. \endtable \sa QTabBar, QStackedWidget, QToolBox, {Tab Dialog Example} diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index d9229c12e8..050730ec2a 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -902,10 +902,10 @@ void QTextBrowser::home() /*! The event \a ev is used to provide the following keyboard shortcuts: \table - \header \i Keypress \i Action - \row \i Alt+Left Arrow \i \l backward() - \row \i Alt+Right Arrow \i \l forward() - \row \i Alt+Up Arrow \i \l home() + \header \li Keypress \li Action + \row \li Alt+Left Arrow \li \l backward() + \row \li Alt+Right Arrow \li \l forward() + \row \li Alt+Up Arrow \li \l home() \endtable */ void QTextBrowser::keyPressEvent(QKeyEvent *ev) @@ -1068,10 +1068,10 @@ void QTextBrowser::paintEvent(QPaintEvent *e) depending on the resource type: \table - \header \i ResourceType \i QVariant::Type - \row \i QTextDocument::HtmlResource \i QString or QByteArray - \row \i QTextDocument::ImageResource \i QImage, QPixmap or QByteArray - \row \i QTextDocument::StyleSheetResource \i QString or QByteArray + \header \li ResourceType \li QVariant::Type + \row \li QTextDocument::HtmlResource \li QString or QByteArray + \row \li QTextDocument::ImageResource \li QImage, QPixmap or QByteArray + \row \li QTextDocument::StyleSheetResource \li QString or QByteArray \endtable */ QVariant QTextBrowser::loadResource(int /*type*/, const QUrl &name) @@ -1146,10 +1146,10 @@ void QTextBrowser::clearHistory() Returns the url of the HistoryItem. \table - \header \i Input \i Return - \row \i \a{i} < 0 \i \l backward() history - \row \i\a{i} == 0 \i current, see QTextBrowser::source() - \row \i \a{i} > 0 \i \l forward() history + \header \li Input \li Return + \row \li \a{i} < 0 \li \l backward() history + \row \li\a{i} == 0 \li current, see QTextBrowser::source() + \row \li \a{i} > 0 \li \l forward() history \endtable \since 4.4 @@ -1164,10 +1164,10 @@ QUrl QTextBrowser::historyUrl(int i) const Returns the documentTitle() of the HistoryItem. \table - \header \i Input \i Return - \row \i \a{i} < 0 \i \l backward() history - \row \i \a{i} == 0 \i current, see QTextBrowser::source() - \row \i \a{i} > 0 \i \l forward() history + \header \li Input \li Return + \row \li \a{i} < 0 \li \l backward() history + \row \li \a{i} == 0 \li current, see QTextBrowser::source() + \row \li \a{i} > 0 \li \l forward() history \endtable \snippet doc/src/snippets/code/src_gui_widgets_qtextbrowser.cpp 0 diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index d0065aacb9..198d101dbf 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -412,19 +412,19 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) When QTextEdit is used read-only the key bindings are limited to navigation, and text may only be selected with the mouse: \table - \header \i Keypresses \i Action - \row \i Up \i Moves one line up. - \row \i Down \i Moves one line down. - \row \i Left \i Moves one character to the left. - \row \i Right \i Moves one character to the right. - \row \i PageUp \i Moves one (viewport) page up. - \row \i PageDown \i Moves one (viewport) page down. - \row \i Home \i Moves to the beginning of the text. - \row \i End \i Moves to the end of the text. - \row \i Alt+Wheel - \i Scrolls the page horizontally (the Wheel is the mouse wheel). - \row \i Ctrl+Wheel \i Zooms the text. - \row \i Ctrl+A \i Selects all text. + \header \li Keypresses \li Action + \row \li Up \li Moves one line up. + \row \li Down \li Moves one line down. + \row \li Left \li Moves one character to the left. + \row \li Right \li Moves one character to the right. + \row \li PageUp \li Moves one (viewport) page up. + \row \li PageDown \li Moves one (viewport) page down. + \row \li Home \li Moves to the beginning of the text. + \row \li End \li Moves to the end of the text. + \row \li Alt+Wheel + \li Scrolls the page horizontally (the Wheel is the mouse wheel). + \row \li Ctrl+Wheel \li Zooms the text. + \row \li Ctrl+A \li Selects all text. \endtable The text edit may be able to provide some meta-information. For @@ -486,31 +486,31 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) The list of key bindings which are implemented for editing: \table - \header \i Keypresses \i Action - \row \i Backspace \i Deletes the character to the left of the cursor. - \row \i Delete \i Deletes the character to the right of the cursor. - \row \i Ctrl+C \i Copy the selected text to the clipboard. - \row \i Ctrl+Insert \i Copy the selected text to the clipboard. - \row \i Ctrl+K \i Deletes to the end of the line. - \row \i Ctrl+V \i Pastes the clipboard text into text edit. - \row \i Shift+Insert \i Pastes the clipboard text into text edit. - \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard. - \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard. - \row \i Ctrl+Z \i Undoes the last operation. - \row \i Ctrl+Y \i Redoes the last operation. - \row \i Left \i Moves the cursor one character to the left. - \row \i Ctrl+Left \i Moves the cursor one word to the left. - \row \i Right \i Moves the cursor one character to the right. - \row \i Ctrl+Right \i Moves the cursor one word to the right. - \row \i Up \i Moves the cursor one line up. - \row \i Down \i Moves the cursor one line down. - \row \i PageUp \i Moves the cursor one page up. - \row \i PageDown \i Moves the cursor one page down. - \row \i Home \i Moves the cursor to the beginning of the line. - \row \i Ctrl+Home \i Moves the cursor to the beginning of the text. - \row \i End \i Moves the cursor to the end of the line. - \row \i Ctrl+End \i Moves the cursor to the end of the text. - \row \i Alt+Wheel \i Scrolls the page horizontally (the Wheel is the mouse wheel). + \header \li Keypresses \li Action + \row \li Backspace \li Deletes the character to the left of the cursor. + \row \li Delete \li Deletes the character to the right of the cursor. + \row \li Ctrl+C \li Copy the selected text to the clipboard. + \row \li Ctrl+Insert \li Copy the selected text to the clipboard. + \row \li Ctrl+K \li Deletes to the end of the line. + \row \li Ctrl+V \li Pastes the clipboard text into text edit. + \row \li Shift+Insert \li Pastes the clipboard text into text edit. + \row \li Ctrl+X \li Deletes the selected text and copies it to the clipboard. + \row \li Shift+Delete \li Deletes the selected text and copies it to the clipboard. + \row \li Ctrl+Z \li Undoes the last operation. + \row \li Ctrl+Y \li Redoes the last operation. + \row \li Left \li Moves the cursor one character to the left. + \row \li Ctrl+Left \li Moves the cursor one word to the left. + \row \li Right \li Moves the cursor one character to the right. + \row \li Ctrl+Right \li Moves the cursor one word to the right. + \row \li Up \li Moves the cursor one line up. + \row \li Down \li Moves the cursor one line down. + \row \li PageUp \li Moves the cursor one page up. + \row \li PageDown \li Moves the cursor one page down. + \row \li Home \li Moves the cursor to the beginning of the line. + \row \li Ctrl+Home \li Moves the cursor to the beginning of the text. + \row \li End \li Moves the cursor to the end of the line. + \row \li Ctrl+End \li Moves the cursor to the end of the text. + \row \li Alt+Wheel \li Scrolls the page horizontally (the Wheel is the mouse wheel). \endtable To select (mark) text hold down the Shift key whilst pressing one diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp index 015419a879..68a4f20fb6 100644 --- a/src/widgets/widgets/qtoolbutton.cpp +++ b/src/widgets/widgets/qtoolbutton.cpp @@ -159,8 +159,8 @@ bool QToolButtonPrivate::hasMenu() const adjust it with setPopupDelay(). \table 100% - \row \o \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons - \row \o Qt Assistant's toolbar contains tool buttons that are associated + \row \li \inlineimage assistant-toolbar.png Qt Assistant's toolbar with tool buttons + \row \li Qt Assistant's toolbar contains tool buttons that are associated with actions used in other parts of the main window. \endtable diff --git a/src/widgets/widgets/qworkspace.cpp b/src/widgets/widgets/qworkspace.cpp index 5cc8e363f1..36c589be1c 100644 --- a/src/widgets/widgets/qworkspace.cpp +++ b/src/widgets/widgets/qworkspace.cpp @@ -878,8 +878,8 @@ QSize QWorkspaceTitleBar::sizeHint() const connect menu entries to them. \table - \row \o \inlineimage mdi-cascade.png - \o \inlineimage mdi-tile.png + \row \li \inlineimage mdi-cascade.png + \li \inlineimage mdi-tile.png \endtable If you want your users to be able to work with child windows diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 0171fc7bef..95fde4e4f6 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -970,8 +970,8 @@ QDomImplementation::~QDomImplementation() The currently supported features and their versions: \table - \header \i Feature \i Version - \row \i XML \i 1.0 + \header \li Feature \li Version + \row \li XML \li 1.0 \endtable */ bool QDomImplementation::hasFeature(const QString& feature, const QString& version) const @@ -2098,22 +2098,22 @@ QDomNode::~QDomNode() The meaning of the name depends on the subclass: \table - \header \i Name \i Meaning - \row \i QDomAttr \i The name of the attribute - \row \i QDomCDATASection \i The string "#cdata-section" - \row \i QDomComment \i The string "#comment" - \row \i QDomDocument \i The string "#document" - \row \i QDomDocumentFragment \i The string "#document-fragment" - \row \i QDomDocumentType \i The name of the document type - \row \i QDomElement \i The tag name - \row \i QDomEntity \i The name of the entity - \row \i QDomEntityReference \i The name of the referenced entity - \row \i QDomNotation \i The name of the notation - \row \i QDomProcessingInstruction \i The target of the processing instruction - \row \i QDomText \i The string "#text" + \header \li Name \li Meaning + \row \li QDomAttr \li The name of the attribute + \row \li QDomCDATASection \li The string "#cdata-section" + \row \li QDomComment \li The string "#comment" + \row \li QDomDocument \li The string "#document" + \row \li QDomDocumentFragment \li The string "#document-fragment" + \row \li QDomDocumentType \li The name of the document type + \row \li QDomElement \li The tag name + \row \li QDomEntity \li The name of the entity + \row \li QDomEntityReference \li The name of the referenced entity + \row \li QDomNotation \li The name of the notation + \row \li QDomProcessingInstruction \li The target of the processing instruction + \row \li QDomText \li The string "#text" \endtable - \bold{Note:} This function does not take the presence of namespaces into account + \b{Note:} This function does not take the presence of namespaces into account when processing the names of element and attribute nodes. As a result, the returned name can contain any namespace prefix that may be present. To obtain the node name of an element or attribute, use localName(); to @@ -2136,12 +2136,12 @@ QString QDomNode::nodeName() const The meaning of the value depends on the subclass: \table - \header \i Name \i Meaning - \row \i QDomAttr \i The attribute value - \row \i QDomCDATASection \i The content of the CDATA section - \row \i QDomComment \i The comment - \row \i QDomProcessingInstruction \i The data of the processing instruction - \row \i QDomText \i The text + \header \li Name \li Meaning + \row \li QDomAttr \li The attribute value + \row \li QDomCDATASection \li The content of the CDATA section + \row \li QDomComment \li The comment + \row \li QDomProcessingInstruction \li The data of the processing instruction + \row \li QDomText \li The text \endtable All the other subclasses do not have a node value and will return @@ -3191,11 +3191,11 @@ bool QDomNamedNodeMapPrivate::containsNS(const QString& nsURI, const QString & l The QDomNamedNodeMap is used in three places: \list 1 - \i QDomDocumentType::entities() returns a map of all entities + \li QDomDocumentType::entities() returns a map of all entities described in the DTD. - \i QDomDocumentType::notations() returns a map of all notations + \li QDomDocumentType::notations() returns a map of all notations described in the DTD. - \i QDomNode::attributes() returns a map of all attributes of an + \li QDomNode::attributes() returns a map of all attributes of an element. \endlist @@ -3427,7 +3427,7 @@ int QDomNamedNodeMap::length() const Returns true if the map contains a node called \a name; otherwise returns false. - \bold{Note:} This function does not take the presence of namespaces into account. + \b{Note:} This function does not take the presence of namespaces into account. Use namedItemNS() to test whether the map contains a node with a specific namespace URI and name. */ @@ -4950,7 +4950,7 @@ QDomNodeList QDomElement::elementsByTagName(const QString& tagname) const Returns true if this element has an attribute called \a name; otherwise returns false. - \bold{Note:} This function does not take the presence of namespaces + \b{Note:} This function does not take the presence of namespaces into account. As a result, the specified name will be tested against fully-qualified attribute names that include any namespace prefixes that may be present. @@ -6692,17 +6692,17 @@ bool QDomDocument::setContent(const QString& text, bool namespaceProcessing, QSt Entity references are handled as follows: \list - \o References to internal general entities and character entities occurring in the + \li References to internal general entities and character entities occurring in the content are included. The result is a QDomText node with the references replaced by their corresponding entity values. - \o References to parameter entities occurring in the internal subset are included. + \li References to parameter entities occurring in the internal subset are included. The result is a QDomDocumentType node which contains entity and notation declarations with the references replaced by their corresponding entity values. - \o Any general parsed entity reference which is not defined in the internal subset and + \li Any general parsed entity reference which is not defined in the internal subset and which occurs in the content is represented as a QDomEntityReference node. - \o Any parsed entity reference which is not defined in the internal subset and which + \li Any parsed entity reference which is not defined in the internal subset and which occurs outside of the content is replaced with an empty string. - \o Any unparsed entity reference is replaced with an empty string. + \li Any unparsed entity reference is replaced with an empty string. \endlist \sa QDomNode::namespaceURI() QDomNode::localName() @@ -7039,46 +7039,46 @@ QDomNodeList QDomDocument::elementsByTagName(const QString& tagname) const The behavior of this function is slightly different depending on the node types: \table - \header \i Node Type \i Behavior - \row \i QDomAttr - \i The owner element is set to 0 and the specified flag is + \header \li Node Type \li Behavior + \row \li QDomAttr + \li The owner element is set to 0 and the specified flag is set to true in the generated attribute. The whole subtree of \a importedNode is always imported for attribute nodes: \a deep has no effect. - \row \i QDomDocument - \i Document nodes cannot be imported. - \row \i QDomDocumentFragment - \i If \a deep is true, this function imports the whole + \row \li QDomDocument + \li Document nodes cannot be imported. + \row \li QDomDocumentFragment + \li If \a deep is true, this function imports the whole document fragment; otherwise it only generates an empty document fragment. - \row \i QDomDocumentType - \i Document type nodes cannot be imported. - \row \i QDomElement - \i Attributes for which QDomAttr::specified() is true are + \row \li QDomDocumentType + \li Document type nodes cannot be imported. + \row \li QDomElement + \li Attributes for which QDomAttr::specified() is true are also imported, other attributes are not imported. If \a deep is true, this function also imports the subtree of \a importedNode; otherwise it imports only the element node (and some attributes, see above). - \row \i QDomEntity - \i Entity nodes can be imported, but at the moment there is + \row \li QDomEntity + \li Entity nodes can be imported, but at the moment there is no way to use them since the document type is read-only in DOM level 2. - \row \i QDomEntityReference - \i Descendants of entity reference nodes are never imported: + \row \li QDomEntityReference + \li Descendants of entity reference nodes are never imported: \a deep has no effect. - \row \i QDomNotation - \i Notation nodes can be imported, but at the moment there is + \row \li QDomNotation + \li Notation nodes can be imported, but at the moment there is no way to use them since the document type is read-only in DOM level 2. - \row \i QDomProcessingInstruction - \i The target and value of the processing instruction is + \row \li QDomProcessingInstruction + \li The target and value of the processing instruction is copied to the new node. - \row \i QDomText - \i The text is copied to the new node. - \row \i QDomCDATASection - \i The text is copied to the new node. - \row \i QDomComment - \i The text is copied to the new node. + \row \li QDomText + \li The text is copied to the new node. + \row \li QDomCDATASection + \li The text is copied to the new node. + \row \li QDomComment + \li The text is copied to the new node. \endtable \sa QDomElement::setAttribute() QDomNode::insertBefore() diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 2a41ce3426..2488d27807 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -516,29 +516,29 @@ private: \list - \o "no error occurred" - \o "error triggered by consumer" - \o "unexpected end of file" - \o "more than one document type definition" - \o "error occurred while parsing element" - \o "tag mismatch" - \o "error occurred while parsing content" - \o "unexpected character" - \o "invalid name for processing instruction" - \o "version expected while reading the XML declaration" - \o "wrong value for standalone declaration" - \o "encoding declaration or standalone declaration expected while reading the XML declaration" - \o "standalone declaration expected while reading the XML declaration" - \o "error occurred while parsing document type definition" - \o "letter is expected" - \o "error occurred while parsing comment" - \o "error occurred while parsing reference" - \o "internal general entity reference not allowed in DTD" - \o "external parsed general entity reference not allowed in attribute value" - \o "external parsed general entity reference not allowed in DTD" - \o "unparsed entity reference n wrong context" - \o "recursive entities" - \o "error in the text declaration of an external entity" + \li "no error occurred" + \li "error triggered by consumer" + \li "unexpected end of file" + \li "more than one document type definition" + \li "error occurred while parsing element" + \li "tag mismatch" + \li "error occurred while parsing content" + \li "unexpected character" + \li "invalid name for processing instruction" + \li "version expected while reading the XML declaration" + \li "wrong value for standalone declaration" + \li "encoding declaration or standalone declaration expected while reading the XML declaration" + \li "standalone declaration expected while reading the XML declaration" + \li "error occurred while parsing document type definition" + \li "letter is expected" + \li "error occurred while parsing comment" + \li "error occurred while parsing reference" + \li "internal general entity reference not allowed in DTD" + \li "external parsed general entity reference not allowed in attribute value" + \li "external parsed general entity reference not allowed in DTD" + \li "unparsed entity reference n wrong context" + \li "recursive entities" + \li "error in the text declaration of an external entity" \endlist Note that, if you want to display these error messages to your @@ -3157,24 +3157,24 @@ bool QXmlSimpleReader::feature(const QString& name, bool *ok) const The \a name parameter must be one of the following strings: \table - \header \i Feature \i Default \i Notes - \row \i \e http://xml.org/sax/features/namespaces - \i true - \i If enabled, namespaces are reported to the content handler. - \row \i \e http://xml.org/sax/features/namespace-prefixes - \i false - \i If enabled, the original prefixed names + \header \li Feature \li Default \li Notes + \row \li \e http://xml.org/sax/features/namespaces + \li true + \li If enabled, namespaces are reported to the content handler. + \row \li \e http://xml.org/sax/features/namespace-prefixes + \li false + \li If enabled, the original prefixed names and attributes used for namespace declarations are reported. - \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData - \i true - \i If enabled, CharData that consist of + \row \li \e http://trolltech.com/xml/features/report-whitespace-only-CharData + \li true + \li If enabled, CharData that consist of only whitespace characters are reported using QXmlContentHandler::characters(). If disabled, whitespace is silently discarded. - \row \i \e http://trolltech.com/xml/features/report-start-end-entity - \i false - \i If enabled, the parser reports + \row \li \e http://trolltech.com/xml/features/report-start-end-entity + \li false + \li If enabled, the parser reports QXmlContentHandler::startEntity() and QXmlContentHandler::endEntity() events, so character data might be reported in chunks. -- cgit v1.2.3 From 7ae38c49b78515e1e49f8a8858ce9c581e534284 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 1 Mar 2012 23:47:36 +0000 Subject: Use QHash instead of QMap when K is a pointer type Changes various internal usages of QMap when the key is a pointer type. Being ordered by the pointer value itself, it makes very little sense to use QMap (esp. in cases where the key is actually allocated on the heap). The usages have been found with the following script: #!/usr/bin/perl use strict; use warnings; use Regexp::Common; use File::Find; use feature ':5.10'; my $container = qr/(?:QMap)/; sub process { return unless (-f and -r and /(\.c|\.cpp|\.h|\.txt)$/); open my $fh, "<", $_ or die "Cannot open $_: $!"; while (my $line = <$fh>) { chomp $line; while ($line =~ /($container\s*$RE{balanced}{-parens=>"<>"})/g) { my $tmp = $1; $tmp =~ s/\s+//g; say "$_:$.: $line" if $tmp =~ /^$container\s*<[^,]+\*,/; } } close $fh; } find( { no_chdir => 1, wanted => \&process }, @ARGV ); Change-Id: Idd9819c3f4c48f98ef92831d5e8e5ac0fa42283c Reviewed-by: Lars Knoll --- src/widgets/graphicsview/qgraphicsitem.cpp | 6 +++--- src/widgets/graphicsview/qgraphicsitem_p.h | 4 ++-- src/widgets/graphicsview/qgraphicsscene_p.h | 2 +- src/widgets/graphicsview/qgraphicswidget.cpp | 2 +- src/widgets/kernel/qapplication_p.h | 4 ++-- src/widgets/kernel/qgesturemanager.cpp | 6 +++--- src/widgets/kernel/qgesturemanager_p.h | 4 ++-- src/widgets/styles/qgtkstyle_p.cpp | 10 +++++----- src/widgets/styles/qgtkstyle_p.h | 2 +- src/widgets/widgets/qabstractbutton.cpp | 2 +- src/widgets/widgets/qwidgetanimator_p.h | 4 ++-- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index d88183fbb5..dab1965da5 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -783,7 +783,7 @@ static inline void _q_adjustRect(QRect *rect) class QGraphicsItemCustomDataStore { public: - QMap > data; + QHash > data; }; Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) @@ -1379,7 +1379,7 @@ void QGraphicsItemCache::purge() { QPixmapCache::remove(key); key = QPixmapCache::Key(); - QMutableMapIterator it(deviceData); + QMutableHashIterator it(deviceData); while (it.hasNext()) { DeviceData &data = it.next().value(); QPixmapCache::remove(data.key); @@ -7124,7 +7124,7 @@ void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) if ((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) { // Determine the list of items that need to be moved. QList selectedItems; - QMap initialPositions; + QHash initialPositions; if (d_ptr->scene) { selectedItems = d_ptr->scene->selectedItems(); initialPositions = d_ptr->scene->d_func()->movingItemsInitialPositions; diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h index aebb22a0ee..1783fdb713 100644 --- a/src/widgets/graphicsview/qgraphicsitem_p.h +++ b/src/widgets/graphicsview/qgraphicsitem_p.h @@ -145,7 +145,7 @@ public: QPoint cacheIndent; QPixmapCache::Key key; }; - QMap deviceData; + QHash deviceData; // List of logical exposed rects QVector exposed; @@ -508,7 +508,7 @@ public: QRectF childrenBoundingRect; QRectF needsRepaint; - QMap paintedViewBoundingRects; + QHash paintedViewBoundingRects; QPointF pos; qreal z; qreal opacity; diff --git a/src/widgets/graphicsview/qgraphicsscene_p.h b/src/widgets/graphicsview/qgraphicsscene_p.h index b0410e38ce..0f5a0a6fc1 100644 --- a/src/widgets/graphicsview/qgraphicsscene_p.h +++ b/src/widgets/graphicsview/qgraphicsscene_p.h @@ -128,7 +128,7 @@ public: QVector unpolishedItems; QList topLevelItems; - QMap movingItemsInitialPositions; + QHash movingItemsInitialPositions; void registerTopLevelItem(QGraphicsItem *item); void unregisterTopLevelItem(QGraphicsItem *item); void _q_updateLater(); diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp index da4ccb1a33..4ad8513050 100644 --- a/src/widgets/graphicsview/qgraphicswidget.cpp +++ b/src/widgets/graphicsview/qgraphicswidget.cpp @@ -222,7 +222,7 @@ public: } private: - QMap styles; + QHash styles; mutable QMutex mutex; }; Q_GLOBAL_STATIC(QGraphicsWidgetStyles, widgetStyles) diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 7a880986bf..ae4f0c2044 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -313,7 +313,7 @@ public: QPointer last_manager; QWSServerCleaner qwsServerCleaner; # ifndef QT_NO_DIRECTPAINTER - QMap *directPainters; + QHash *directPainters; # endif QRect maxWindowRect(const QScreen *screen) const { return maxWindowRects[screen]; } void setMaxWindowRect(const QScreen *screen, int screenNo, const QRect &rect); @@ -393,7 +393,7 @@ public: private: #ifdef Q_WS_QWS - QMap maxWindowRects; + QHash maxWindowRects; #endif static QApplicationPrivate *self; diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 2e9edb1481..296d8d31e7 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -541,8 +541,8 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event) } void QGestureManager::getGestureTargets(const QSet &gestures, - QMap > *conflicts, - QMap > *normal) + QHash > *conflicts, + QHash > *normal) { typedef QHash > GestureByTypes; GestureByTypes gestureByTypes; @@ -588,7 +588,7 @@ void QGestureManager::deliverEvents(const QSet &gestures, if (gestures.isEmpty()) return; - typedef QMap > GesturesPerWidget; + typedef QHash > GesturesPerWidget; GesturesPerWidget conflictedGestures; GesturesPerWidget normalStartedGestures; diff --git a/src/widgets/kernel/qgesturemanager_p.h b/src/widgets/kernel/qgesturemanager_p.h index 68945a7b66..9f59550bb1 100644 --- a/src/widgets/kernel/qgesturemanager_p.h +++ b/src/widgets/kernel/qgesturemanager_p.h @@ -138,8 +138,8 @@ private: void deliverEvents(const QSet &gestures, QSet *undeliveredGestures); void getGestureTargets(const QSet &gestures, - QMap > *conflicts, - QMap > *normal); + QHash > *conflicts, + QHash > *normal); void cancelGesturesForChildren(QGesture *originatingGesture); }; diff --git a/src/widgets/styles/qgtkstyle_p.cpp b/src/widgets/styles/qgtkstyle_p.cpp index 18e120a4eb..0402859e31 100644 --- a/src/widgets/styles/qgtkstyle_p.cpp +++ b/src/widgets/styles/qgtkstyle_p.cpp @@ -897,7 +897,7 @@ extern QStringList qt_make_filter_list(const QString &filter); void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, bool isSaveDialog, - QMap *filterMap) + QHash *filterMap) { g_object_set(gtkFileChooser, "do-overwrite-confirmation", gboolean(!(options & QFileDialog::DontConfirmOverwrite)), NULL); g_object_set(gtkFileChooser, "local_only", gboolean(true), NULL); @@ -969,7 +969,7 @@ void QGtkStylePrivate::setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *p QString QGtkStylePrivate::openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - QMap filterMap; + QHash filterMap; GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, @@ -1003,7 +1003,7 @@ QString QGtkStylePrivate::openFilename(QWidget *parent, const QString &caption, QString QGtkStylePrivate::openDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) { - QMap filterMap; + QHash filterMap; GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, @@ -1033,7 +1033,7 @@ QStringList QGtkStylePrivate::openFilenames(QWidget *parent, const QString &capt QString *selectedFilter, QFileDialog::Options options) { QStringList filenames; - QMap filterMap; + QHash filterMap; GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, @@ -1068,7 +1068,7 @@ QStringList QGtkStylePrivate::openFilenames(QWidget *parent, const QString &capt QString QGtkStylePrivate::saveFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { - QMap filterMap; + QHash filterMap; GtkWidget *gtkFileChooser = QGtkStylePrivate::gtk_file_chooser_dialog_new (qPrintable(caption), NULL, GTK_FILE_CHOOSER_ACTION_SAVE, diff --git a/src/widgets/styles/qgtkstyle_p.h b/src/widgets/styles/qgtkstyle_p.h index 95988fa8b1..02d659c1e4 100644 --- a/src/widgets/styles/qgtkstyle_p.h +++ b/src/widgets/styles/qgtkstyle_p.h @@ -344,7 +344,7 @@ public: static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options, bool isSaveDialog = false, - QMap *filterMap = 0); + QHash *filterMap = 0); static QString openFilename(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options); diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 2c51e89c43..80e125947e 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -190,7 +190,7 @@ public: void detectCheckedButton(); void notifyChecked(QAbstractButton *button); bool exclusive; - QMap mapping; + QHash mapping; }; QButtonGroup::QButtonGroup(QObject *parent) diff --git a/src/widgets/widgets/qwidgetanimator_p.h b/src/widgets/widgets/qwidgetanimator_p.h index e2054401d6..82f81a704f 100644 --- a/src/widgets/widgets/qwidgetanimator_p.h +++ b/src/widgets/widgets/qwidgetanimator_p.h @@ -54,7 +54,7 @@ // #include -#include +#include QT_BEGIN_NAMESPACE @@ -79,7 +79,7 @@ private Q_SLOTS: #endif private: - typedef QMap AnimationMap; + typedef QHash AnimationMap; AnimationMap m_animation_map; QMainWindowLayout *m_mainWindowLayout; }; -- cgit v1.2.3 From db1abf9f760ebc40b1f7f0f3e88698cea8aebbd7 Mon Sep 17 00:00:00 2001 From: Sergio Ahumada Date: Fri, 2 Mar 2012 11:04:01 +0100 Subject: Change bugreports.qt.nokia.com -> bugreports.qt-project.org Change-Id: Ia795098f24cf358b15067f54cd08dff0bd792bc5 Reviewed-by: Thiago Macieira --- dist/README | 2 +- dist/changes-5.0.0 | 2 +- examples/webkit/webkit-guide/_index.html | 2 +- src/corelib/global/qnamespace.qdoc | 2 +- src/network/access/qhttpnetworkconnectionchannel.cpp | 2 +- src/network/access/qnetworkcookie.cpp | 4 ++-- src/platformsupport/eglconvenience/qxlibeglintegration.cpp | 2 +- tests/auto/gui/image/qimagereader/tst_qimagereader.cpp | 2 +- tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dist/README b/dist/README index 815e12be9e..1206280265 100644 --- a/dist/README +++ b/dist/README @@ -74,7 +74,7 @@ HOW TO REPORT A BUG If you think you have found a bug in Qt, we would like to hear about it so that we can fix it. The Qt bug tracking system is open to the -public at http://bugreports.qt.nokia.com/. +public at http://bugreports.qt-project.org/. Before reporting a bug, please use the bug-tracker's search functions and consult http://qt.nokia.com/developer/faqs/ to see if the issue is diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index ef1bd6d406..9ab96fb8d8 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -1,7 +1,7 @@ Some of the changes listed in this file include issue tracking numbers corresponding to tasks in the Qt Bug Tracker: - http://bugreports.qt.nokia.com/ + http://bugreports.qt-project.org/ Each of these identifiers can be entered in the bug tracker to obtain more information about a particular change. diff --git a/examples/webkit/webkit-guide/_index.html b/examples/webkit/webkit-guide/_index.html index 5d7dd11d63..f3a1f9dfa6 100644 --- a/examples/webkit/webkit-guide/_index.html +++ b/examples/webkit/webkit-guide/_index.html @@ -298,7 +298,7 @@ entered (localStorage), but credit-card data s/b absent
X

Thank you for giving your feedback.

Make sure it is related to this specific page. For more general bugs and - requests, please use the Qt Bug Tracker.

+ requests, please use the Qt Bug Tracker.

diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 7d5eec4271..1df36f42e6 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2653,7 +2653,7 @@ \value ElideNone Ellipsis should NOT appear in the text. Qt::ElideMiddle is normally the most appropriate choice for URLs (e.g., - "\l{http://bugreports.qt.nokia.com/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"), + "\l{http://bugreports.qt-project.org/browse/QTWEBSITE-13}{http://bugreports.qt.../QTWEBSITE-13/}"), whereas Qt::ElideRight is appropriate for other strings (e.g., "\l{http://qt.nokia.com/doc/qq/qq09-mac-deployment.html}{Deploying Applications on Ma...}"). diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index e4ea62f093..3991bffa47 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -646,7 +646,7 @@ void QHttpNetworkConnectionChannel::allDone() Q_ASSERT(reply); if (!reply) { - qWarning() << "QHttpNetworkConnectionChannel::allDone() called without reply. Please report at http://bugreports.qt.nokia.com/"; + qWarning() << "QHttpNetworkConnectionChannel::allDone() called without reply. Please report at http://bugreports.qt-project.org/"; return; } diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 88b021d780..0dbfdb2f0c 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -409,7 +409,7 @@ static QPair nextField(const QByteArray &text, int &posi // quoted-pair = "\" CHAR // If it is NAME=VALUE, retain the value as is - // refer to http://bugreports.qt.nokia.com/browse/QTBUG-17746 + // refer to http://bugreports.qt-project.org/browse/QTBUG-17746 if (isNameValue) second += '"'; ++i; @@ -1060,7 +1060,7 @@ QList QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt */ void QNetworkCookie::normalize(const QUrl &url) { - // don't do path checking. See http://bugreports.qt.nokia.com/browse/QTBUG-5815 + // don't do path checking. See http://bugreports.qt-project.org/browse/QTBUG-5815 if (d->path.isEmpty()) { QString pathAndFileName = url.path(); QString defaultPath = pathAndFileName.left(pathAndFileName.lastIndexOf(QLatin1Char('/'))+1); diff --git a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp index 0f6e2ae8d5..3d3253be64 100644 --- a/src/platformsupport/eglconvenience/qxlibeglintegration.cpp +++ b/src/platformsupport/eglconvenience/qxlibeglintegration.cpp @@ -86,7 +86,7 @@ VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount); if (chosenVisualInfo) { // Skip size checks if implementation supports non-matching visual - // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). + // and config (http://bugreports.qt-project.org/browse/QTBUG-9444). if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) { XFree(chosenVisualInfo); return visualId; diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index dd839ec0ae..6f6662a80f 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -772,7 +772,7 @@ void tst_QImageReader::animatedGif() } } -// http://bugreports.qt.nokia.com/browse/QTBUG-6696 +// http://bugreports.qt-project.org/browse/QTBUG-6696 // Check the count of images in various call orders... void tst_QImageReader::gifImageCount() { diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 5b34fa7c29..d8f9bf32ad 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -6474,7 +6474,7 @@ void tst_QNetworkReply::synchronousRequest() // workaround for HTTPS requests: add self-signed server cert to list of CA certs, // since we cannot react to the sslErrors() signal // to fix this properly we would need to have an ignoreSslErrors() method in the - // QNetworkRequest, see http://bugreports.qt.nokia.com/browse/QTBUG-14774 + // QNetworkRequest, see http://bugreports.qt-project.org/browse/QTBUG-14774 if (url.scheme() == "https") { QSslConfiguration sslConf; QList certs = QSslCertificate::fromPath(testDataDir + "/certs/qt-test-server-cacert.pem"); -- cgit v1.2.3 From 87975f88ce72b803fe3fa982540b940c2e205009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lund=20Martsum?= Date: Thu, 23 Feb 2012 15:53:51 +0100 Subject: QAbstractSlider - adding setRange as a slot In many situations it would be very nice to have setRange as a slot. It fits good with the rangeChanged signal - and in some situations it does make sense to synchronize scrollbars ranges. Change-Id: I6bcb41ed6e009e5822b56b621e4e187fe52502a6 Reviewed-by: Robin Burchell --- src/widgets/widgets/qabstractslider.h | 3 +-- .../widgets/widgets/qabstractslider/tst_qabstractslider.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qabstractslider.h b/src/widgets/widgets/qabstractslider.h index dbcd14cb67..d03a1a3918 100644 --- a/src/widgets/widgets/qabstractslider.h +++ b/src/widgets/widgets/qabstractslider.h @@ -79,8 +79,6 @@ public: void setMaximum(int); int maximum() const; - void setRange(int min, int max); - void setSingleStep(int); int singleStep() const; @@ -120,6 +118,7 @@ public: public Q_SLOTS: void setValue(int); void setOrientation(Qt::Orientation); + void setRange(int min, int max); Q_SIGNALS: void valueChanged(int value); diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp index 6021f90ed4..cff847474c 100644 --- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp +++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp @@ -93,6 +93,7 @@ private slots: void setValue_data(); void setValue(); void setRepeatAction(); + void connectedSliders(); private: void waitUntilTimeElapsed(const QTime& t, int ms); @@ -1259,5 +1260,17 @@ void tst_QAbstractSlider::setRepeatAction() QCOMPARE(slider->value(), 115); } +void tst_QAbstractSlider::connectedSliders() +{ + Slider *slider2 = new Slider(topLevel); + connect(slider, SIGNAL(rangeChanged(int, int)), slider2, SLOT(setRange(int, int))); + const int sliderlow = 13; + const int sliderhigh = 1017; + slider->setRange(sliderlow, sliderhigh); + QCOMPARE(slider2->minimum(), sliderlow); + QCOMPARE(slider2->maximum(), sliderhigh); + delete slider2; +} + QTEST_MAIN(tst_QAbstractSlider) #include "tst_qabstractslider.moc" -- cgit v1.2.3 From 3280b919855dae6de4319450ff352d1c493649a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 2 Mar 2012 18:25:22 +0100 Subject: Cleaned up debug and warning output in xcb plugin. Got rid of unnecessary debug output, and prefixed debug / warnings with class name to provide more context. Change-Id: Ia68e85ec0207de4d87d02226bdf6e4cddf464afc Reviewed-by: Uli Schlachter Reviewed-by: Robin Burchell --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 18 ++++++++-------- src/plugins/platforms/xcb/qxcbconnection.cpp | 25 +++++++++++----------- src/plugins/platforms/xcb/qxcbimage.cpp | 8 +++---- src/plugins/platforms/xcb/qxcbintegration.cpp | 6 ++++-- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 2 +- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 4 ++++ .../platforms/xcb/qxcbsharedbuffermanager.cpp | 2 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ++-- src/plugins/platforms/xcb/qxcbwmsupport.cpp | 7 ++---- 10 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index f8d35ed4da..63ce73993f 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -74,7 +74,7 @@ public: break; default: - qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode"); + qWarning("QXcbClipboardMime: Internal error: Unsupported clipboard mode"); break; } } @@ -209,7 +209,7 @@ QXcbClipboard::~QXcbClipboard() // waiting until the clipboard manager fetches the content. if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) { - qWarning("QClipboard: Unable to receive an event from the " + qWarning("QXcbClipboard: Unable to receive an event from the " "clipboard manager in a reasonable time"); } } @@ -292,7 +292,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) xcb_set_selection_owner(xcb_connection(), newOwner, modeAtom, connection()->time()); if (getSelectionOwner(modeAtom) != newOwner) { - qWarning("QClipboard::setData: Cannot set X11 selection owner"); + qWarning("QXcbClipboard::setData: Cannot set X11 selection owner"); } emitChanged(mode); @@ -403,7 +403,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes); // (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); - qWarning() << "not implemented INCR just YET!"; + qWarning("QXcbClipboard: INCR is unimplemented"); return property; } @@ -445,7 +445,7 @@ void QXcbClipboard::handleSelectionClearRequest(xcb_selection_clear_event_t *eve void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) { if (requestor() && req->requestor == requestor()) { - qDebug() << "This should be caught before"; + qWarning("QXcbClipboard: Selection request should be caught before"); return; } @@ -460,7 +460,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) QMimeData *d; QClipboard::Mode mode = modeForAtom(req->selection); if (mode > QClipboard::Selection) { - qWarning() << "QClipboard: Unknown selection" << connection()->atomName(req->selection); + qWarning() << "QXcbClipboard: Unknown selection" << connection()->atomName(req->selection); xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); return; } @@ -468,14 +468,14 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) d = m_clientClipboard[mode]; if (!d) { - qWarning("QClipboard: Cannot transfer data, no data available"); + qWarning("QXcbClipboard: Cannot transfer data, no data available"); xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); return; } if (m_timestamp[mode] == XCB_CURRENT_TIME // we don't own the selection anymore || (req->time != XCB_CURRENT_TIME && req->time < m_timestamp[mode])) { - qDebug("QClipboard: SelectionRequest too old"); + qWarning("QXcbClipboard: SelectionRequest too old"); xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); return; } @@ -530,7 +530,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) property, XCB_ATOM_INTEGER, 32, 1, &m_timestamp[mode]); ret = property; } else { - qWarning("QClipboard: Invalid data timestamp"); + qWarning("QXcbClipboard: Invalid data timestamp"); } } else if (target == xa_targets) { ret = sendTargetsSelection(d, req->requestor, property); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 90df387f6a..367b24da9d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -135,7 +135,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char #endif //XCB_USE_XLIB if (!m_connection || xcb_connection_has_error(m_connection)) - qFatal("Could not connect to display %s", m_displayName.constData()); + qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); m_reader = new QXcbEventReader(this); #ifdef XCB_POLL_FOR_QUEUED_EVENT @@ -255,7 +255,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) #ifdef XCB_EVENT_DEBUG #define PRINT_XCB_EVENT(ev) \ case ev: \ - qDebug("%s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \ + qDebug("QXcbConnection: %s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \ break; switch (event->response_type & ~0x80) { @@ -292,7 +292,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event) PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE); PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY); default: - qDebug("%s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence)); + qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence)); } #else Q_UNUSED(message); @@ -465,7 +465,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) uint clamped_error_code = qMin(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); uint clamped_major_code = qMin(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - qDebug("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", + qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", int(error->error_code), xcb_errors[clamped_error_code], int(error->sequence), int(error->resource_id), int(error->major_code), xcb_protocol_request_codes[clamped_major_code], @@ -557,7 +557,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) break; case XCB_SELECTION_NOTIFY: setTime(((xcb_selection_notify_event_t *)event)->time); - qDebug() << "XCB_SELECTION_NOTIFY"; handled = false; break; case XCB_PROPERTY_NOTIFY: @@ -1029,7 +1028,7 @@ void QXcbConnection::initializeXFixes() xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection, xfixes_query_cookie, &error); if (!xfixes_query || error || xfixes_query->major_version < 2) { - qWarning("Failed to initialize XFixes"); + qWarning("QXcbConnection: Failed to initialize XFixes"); free(error); xfixes_first_event = 0; } @@ -1046,7 +1045,7 @@ void QXcbConnection::initializeXRender() xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection, xrender_query_cookie, &error); if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) { - qWarning("Failed to initialize XRender"); + qWarning("QXcbConnection: Failed to initialize XRender"); free(error); } free(xrender_query); @@ -1090,7 +1089,7 @@ void QXcbConnection::initializeDri2() connect_cookie, NULL); if (! connect || connect->driver_name_length + connect->device_name_length == 0) { - qDebug() << "Failed to connect to dri2"; + qWarning("QXcbConnection: Failed to connect to DRI2"); return; } @@ -1100,14 +1099,14 @@ void QXcbConnection::initializeDri2() int fd = open(m_dri2_device_name.constData(), O_RDWR); if (fd < 0) { - qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName"; + qWarning() << "QXcbConnection: Couldn't open DRI2 device" << m_dri2_device_name; m_dri2_device_name = QByteArray(); return; } drm_magic_t magic; if (drmGetMagic(fd, &magic)) { - qDebug() << "Failed to get drmMagic"; + qWarning("QXcbConnection: Failed to get drmMagic"); return; } @@ -1116,7 +1115,7 @@ void QXcbConnection::initializeDri2() xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection, authenticate_cookie, NULL); if (authenticate == NULL || !authenticate->authenticated) { - qWarning("DRI2: failed to authenticate"); + qWarning("QXcbConnection: DRI2: failed to authenticate"); free(authenticate); return; } @@ -1125,14 +1124,14 @@ void QXcbConnection::initializeDri2() EGLDisplay display = eglGetDRMDisplayMESA(fd); if (!display) { - qWarning("failed to create display"); + qWarning("QXcbConnection: Failed to create EGL display using DRI2"); return; } m_egl_display = display; EGLint major,minor; if (!eglInitialize(display, &major, &minor)) { - qWarning("failed to initialize display"); + qWarning("QXcbConnection: Failed to initialize EGL display using DRI2"); return; } } diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index 13ff8ab2a5..12979bfb68 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -201,7 +201,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, formatsCookie, &error); if (!formatsReply || error) { - qWarning("createCursorXRender: query_pict_formats failed"); + qWarning("qt_xcb_createCursorXRender: query_pict_formats failed"); free(formatsReply); free(error); return XCB_NONE; @@ -209,7 +209,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply, XCB_PICT_STANDARD_ARGB_32); if (!fmt) { - qWarning("createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32"); + qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32"); free(formatsReply); return XCB_NONE; } @@ -221,13 +221,13 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image, XCB_IMAGE_ORDER_MSB_FIRST, 0, 0, 0); if (!xi) { - qWarning("createCursorXRender: xcb_image_create failed"); + qWarning("qt_xcb_createCursorXRender: xcb_image_create failed"); free(formatsReply); return XCB_NONE; } xi->data = (uint8_t *) malloc(xi->stride * h); if (!xi->data) { - qWarning("createCursorXRender: Failed to malloc() image data"); + qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data"); xcb_image_destroy(xi); free(formatsReply); return XCB_NONE; diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 98f69e9e16..fe33bd7153 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -101,7 +101,9 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters) m_connections << new QXcbConnection(m_nativeInterface.data()); for (int i = 0; i < parameters.size() - 1; i += 2) { - qDebug() << parameters.at(i) << parameters.at(i+1); +#ifdef Q_XCB_DEBUG + qDebug() << "QXcbIntegration: Connecting to additional display: " << parameters.at(i) << parameters.at(i+1); +#endif QString display = parameters.at(i) + ':' + parameters.at(i+1); m_connections << new QXcbConnection(m_nativeInterface.data(), display.toAscii().constData()); } @@ -185,7 +187,7 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont #elif defined(XCB_USE_DRI2) return new QDri2Context(context->format(), context->shareHandle()); #endif - qWarning("Cannot create platform GL context, none of GLX, EGL, DRI2 is enabled"); + qWarning("QXcbIntegration: Cannot create platform OpenGL context, none of GLX, EGL, or DRI2 are enabled"); return 0; } #endif diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index b682b87bc3..03156dc544 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -935,7 +935,7 @@ void QXcbKeyboard::setupModifiers() xcb_get_modifier_mapping_reply_t *modMapReply = xcb_get_modifier_mapping_reply(conn, modMapCookie, &error); if (error) { - qWarning("xcb keyboard: failed to get modifier mapping"); + qWarning("QXcbKeyboard: failed to get modifier mapping"); free(error); return; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 406f9c24bd..f56072f9d7 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -137,7 +137,7 @@ QPlatformNativeInterface::EventFilter QXcbNativeInterface::setEventFilter(const if (eventType == QByteArrayLiteral("xcb_generic_event_t")) type = GenericEventFilter; if (type == -1) { - qWarning("%s: Attempt to set invalid event filter type '%s'.", + qWarning("QXcbNativeInterface: %s: Attempt to set invalid event filter type '%s'.", Q_FUNC_INFO, eventType.constData()); return 0; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index c93b4863e1..15ffc5b8ff 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -55,6 +55,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num , m_screen(screen) , m_number(number) { +#ifdef Q_XCB_DEBUG qDebug(); qDebug("Information of screen %d:", screen->root); qDebug(" width.........: %d", screen->width_in_pixels); @@ -63,6 +64,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num qDebug(" white pixel...: %x", screen->white_pixel); qDebug(" black pixel...: %x", screen->black_pixel); qDebug(); +#endif const quint32 mask = XCB_CW_EVENT_MASK; const quint32 values[] = { @@ -93,7 +95,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num atom(QXcbAtom::UTF8_STRING), 0, 1024), &error); if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) { m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply)); +#ifdef Q_XCB_DEBUG qDebug("Running window manager: %s", qPrintable(m_windowManagerName)); +#endif } else if (error) { connection->handleXcbError(error); free(error); diff --git a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp index f9e388b662..8bd3aea259 100644 --- a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp +++ b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp @@ -581,7 +581,7 @@ QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::allocateBuffer(int wid bool ok = buffer->buffer->create(buffer->width * buffer->height * buffer->bytesPerPixel, QSharedMemory::ReadWrite); if (!ok) { - qWarning("SharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)", + qWarning("QXcbSharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)", qPrintable(buffer->buffer->errorString())); delete buffer; return 0; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 7777820e93..739426a92a 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1281,7 +1281,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even m_syncValue.lo = event->data.data32[2]; m_syncValue.hi = event->data.data32[3]; } else { - qWarning() << "unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]); + qWarning() << "QXcbWindow: Unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]); } } else if (event->type == atom(QXcbAtom::XdndEnter)) { connection()->drag()->handleEnter(window(), event); @@ -1292,7 +1292,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even } else if (event->type == atom(QXcbAtom::XdndDrop)) { connection()->drag()->handleDrop(window(), event); } else { - qWarning() << "unhandled client message:" << connection()->atomName(event->type); + qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type); } } diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp index 114049f911..c9f4ca69dd 100644 --- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp +++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp @@ -89,11 +89,6 @@ void QXcbWMSupport::updateNetWMAtoms() free(reply); } while (remaining > 0); - -// qDebug() << "======== updateNetWMAtoms"; -// for (int i = 0; i < net_wm_atoms.size(); ++i) -// qDebug() << atomName(net_wm_atoms.at(i)); -// qDebug() << "======== updateNetWMAtoms"; } // update the virtual roots array @@ -130,10 +125,12 @@ void QXcbWMSupport::updateVirtualRoots() free(reply); } while (remaining > 0); +#ifdef Q_XCB_DEBUG qDebug() << "======== updateVirtualRoots"; for (int i = 0; i < net_virtual_roots.size(); ++i) qDebug() << connection()->atomName(net_virtual_roots.at(i)); qDebug() << "======== updateVirtualRoots"; +#endif } QT_END_NAMESPACE -- cgit v1.2.3 From ddf4faf33f2aea33952abc27835ab982d93eb9ef Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 23 Jan 2012 23:06:27 +0000 Subject: QRegularExpression: import PCRE under 3rdparty/ Imported only the minimum subset of PCRE version 8.30, without documentation, tests, examples, etc. by using the import_from_pcre_tarball.sh script. Change-Id: Ib1112a6179789814cc3c90cbde59408d2ccd0f57 Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- src/3rdparty/pcre/AUTHORS | 45 + src/3rdparty/pcre/COPYING | 5 + src/3rdparty/pcre/LICENCE | 92 + src/3rdparty/pcre/pcre.h | 503 ++ src/3rdparty/pcre/pcre16_byte_order.c | 45 + src/3rdparty/pcre/pcre16_chartables.c | 45 + src/3rdparty/pcre/pcre16_compile.c | 45 + src/3rdparty/pcre/pcre16_config.c | 45 + src/3rdparty/pcre/pcre16_dfa_exec.c | 45 + src/3rdparty/pcre/pcre16_exec.c | 45 + src/3rdparty/pcre/pcre16_fullinfo.c | 45 + src/3rdparty/pcre/pcre16_get.c | 45 + src/3rdparty/pcre/pcre16_globals.c | 45 + src/3rdparty/pcre/pcre16_jit_compile.c | 45 + src/3rdparty/pcre/pcre16_maketables.c | 45 + src/3rdparty/pcre/pcre16_newline.c | 45 + src/3rdparty/pcre/pcre16_ord2utf16.c | 95 + src/3rdparty/pcre/pcre16_refcount.c | 45 + src/3rdparty/pcre/pcre16_string_utils.c | 45 + src/3rdparty/pcre/pcre16_study.c | 45 + src/3rdparty/pcre/pcre16_tables.c | 45 + src/3rdparty/pcre/pcre16_ucd.c | 45 + src/3rdparty/pcre/pcre16_utf16_utils.c | 129 + src/3rdparty/pcre/pcre16_valid_utf16.c | 146 + src/3rdparty/pcre/pcre16_version.c | 45 + src/3rdparty/pcre/pcre16_xclass.c | 45 + src/3rdparty/pcre/pcre_byte_order.c | 288 + src/3rdparty/pcre/pcre_chartables.c | 198 + src/3rdparty/pcre/pcre_compile.c | 8162 ++++++++++++++++++++++ src/3rdparty/pcre/pcre_config.c | 170 + src/3rdparty/pcre/pcre_dfa_exec.c | 3490 +++++++++ src/3rdparty/pcre/pcre_exec.c | 6960 ++++++++++++++++++ src/3rdparty/pcre/pcre_fullinfo.c | 202 + src/3rdparty/pcre/pcre_get.c | 587 ++ src/3rdparty/pcre/pcre_globals.c | 84 + src/3rdparty/pcre/pcre_internal.h | 2332 +++++++ src/3rdparty/pcre/pcre_jit_compile.c | 6915 ++++++++++++++++++ src/3rdparty/pcre/pcre_maketables.c | 148 + src/3rdparty/pcre/pcre_newline.c | 184 + src/3rdparty/pcre/pcre_ord2utf8.c | 97 + src/3rdparty/pcre/pcre_refcount.c | 89 + src/3rdparty/pcre/pcre_string_utils.c | 168 + src/3rdparty/pcre/pcre_study.c | 1527 ++++ src/3rdparty/pcre/pcre_tables.c | 568 ++ src/3rdparty/pcre/pcre_ucd.c | 2981 ++++++++ src/3rdparty/pcre/pcre_valid_utf8.c | 299 + src/3rdparty/pcre/pcre_version.c | 95 + src/3rdparty/pcre/pcre_xclass.c | 198 + src/3rdparty/pcre/sljit/sljitConfig.h | 96 + src/3rdparty/pcre/sljit/sljitConfigInternal.h | 424 ++ src/3rdparty/pcre/sljit/sljitExecAllocator.c | 277 + src/3rdparty/pcre/sljit/sljitLir.c | 1594 +++++ src/3rdparty/pcre/sljit/sljitLir.h | 853 +++ src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c | 1913 +++++ src/3rdparty/pcre/sljit/sljitNativeARM_v5.c | 2424 +++++++ src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c | 405 ++ src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c | 1829 +++++ src/3rdparty/pcre/sljit/sljitNativePPC_32.c | 262 + src/3rdparty/pcre/sljit/sljitNativePPC_64.c | 428 ++ src/3rdparty/pcre/sljit/sljitNativePPC_common.c | 1872 +++++ src/3rdparty/pcre/sljit/sljitNativeX86_32.c | 517 ++ src/3rdparty/pcre/sljit/sljitNativeX86_64.c | 842 +++ src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 2858 ++++++++ src/3rdparty/pcre/sljit/sljitUtils.c | 244 + src/3rdparty/pcre/ucp.h | 165 + 65 files changed, 54615 insertions(+) create mode 100644 src/3rdparty/pcre/AUTHORS create mode 100644 src/3rdparty/pcre/COPYING create mode 100644 src/3rdparty/pcre/LICENCE create mode 100644 src/3rdparty/pcre/pcre.h create mode 100644 src/3rdparty/pcre/pcre16_byte_order.c create mode 100644 src/3rdparty/pcre/pcre16_chartables.c create mode 100644 src/3rdparty/pcre/pcre16_compile.c create mode 100644 src/3rdparty/pcre/pcre16_config.c create mode 100644 src/3rdparty/pcre/pcre16_dfa_exec.c create mode 100644 src/3rdparty/pcre/pcre16_exec.c create mode 100644 src/3rdparty/pcre/pcre16_fullinfo.c create mode 100644 src/3rdparty/pcre/pcre16_get.c create mode 100644 src/3rdparty/pcre/pcre16_globals.c create mode 100644 src/3rdparty/pcre/pcre16_jit_compile.c create mode 100644 src/3rdparty/pcre/pcre16_maketables.c create mode 100644 src/3rdparty/pcre/pcre16_newline.c create mode 100644 src/3rdparty/pcre/pcre16_ord2utf16.c create mode 100644 src/3rdparty/pcre/pcre16_refcount.c create mode 100644 src/3rdparty/pcre/pcre16_string_utils.c create mode 100644 src/3rdparty/pcre/pcre16_study.c create mode 100644 src/3rdparty/pcre/pcre16_tables.c create mode 100644 src/3rdparty/pcre/pcre16_ucd.c create mode 100644 src/3rdparty/pcre/pcre16_utf16_utils.c create mode 100644 src/3rdparty/pcre/pcre16_valid_utf16.c create mode 100644 src/3rdparty/pcre/pcre16_version.c create mode 100644 src/3rdparty/pcre/pcre16_xclass.c create mode 100644 src/3rdparty/pcre/pcre_byte_order.c create mode 100644 src/3rdparty/pcre/pcre_chartables.c create mode 100644 src/3rdparty/pcre/pcre_compile.c create mode 100644 src/3rdparty/pcre/pcre_config.c create mode 100644 src/3rdparty/pcre/pcre_dfa_exec.c create mode 100644 src/3rdparty/pcre/pcre_exec.c create mode 100644 src/3rdparty/pcre/pcre_fullinfo.c create mode 100644 src/3rdparty/pcre/pcre_get.c create mode 100644 src/3rdparty/pcre/pcre_globals.c create mode 100644 src/3rdparty/pcre/pcre_internal.h create mode 100644 src/3rdparty/pcre/pcre_jit_compile.c create mode 100644 src/3rdparty/pcre/pcre_maketables.c create mode 100644 src/3rdparty/pcre/pcre_newline.c create mode 100644 src/3rdparty/pcre/pcre_ord2utf8.c create mode 100644 src/3rdparty/pcre/pcre_refcount.c create mode 100644 src/3rdparty/pcre/pcre_string_utils.c create mode 100644 src/3rdparty/pcre/pcre_study.c create mode 100644 src/3rdparty/pcre/pcre_tables.c create mode 100644 src/3rdparty/pcre/pcre_ucd.c create mode 100644 src/3rdparty/pcre/pcre_valid_utf8.c create mode 100644 src/3rdparty/pcre/pcre_version.c create mode 100644 src/3rdparty/pcre/pcre_xclass.c create mode 100644 src/3rdparty/pcre/sljit/sljitConfig.h create mode 100644 src/3rdparty/pcre/sljit/sljitConfigInternal.h create mode 100644 src/3rdparty/pcre/sljit/sljitExecAllocator.c create mode 100644 src/3rdparty/pcre/sljit/sljitLir.c create mode 100644 src/3rdparty/pcre/sljit/sljitLir.h create mode 100644 src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeARM_v5.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativePPC_32.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativePPC_64.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativePPC_common.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeX86_32.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeX86_64.c create mode 100644 src/3rdparty/pcre/sljit/sljitNativeX86_common.c create mode 100644 src/3rdparty/pcre/sljit/sljitUtils.c create mode 100644 src/3rdparty/pcre/ucp.h diff --git a/src/3rdparty/pcre/AUTHORS b/src/3rdparty/pcre/AUTHORS new file mode 100644 index 0000000000..ba4753d858 --- /dev/null +++ b/src/3rdparty/pcre/AUTHORS @@ -0,0 +1,45 @@ +THE MAIN PCRE LIBRARY +--------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk + +University of Cambridge Computing Service, +Cambridge, England. + +Copyright (c) 1997-2012 University of Cambridge +All rights reserved + + +PCRE JUST-IN-TIME COMPILATION SUPPORT +------------------------------------- + +Written by: Zoltan Herczeg +Email local part: hzmester +Emain domain: freemail.hu + +Copyright(c) 2010-2012 Zoltan Herczeg +All rights reserved. + + +STACK-LESS JUST-IN-TIME COMPILER +-------------------------------- + +Written by: Zoltan Herczeg +Email local part: hzmester +Emain domain: freemail.hu + +Copyright(c) 2009-2012 Zoltan Herczeg +All rights reserved. + + +THE C++ WRAPPER LIBRARY +----------------------- + +Written by: Google Inc. + +Copyright (c) 2007-2012 Google Inc +All rights reserved + +#### diff --git a/src/3rdparty/pcre/COPYING b/src/3rdparty/pcre/COPYING new file mode 100644 index 0000000000..58eed01b61 --- /dev/null +++ b/src/3rdparty/pcre/COPYING @@ -0,0 +1,5 @@ +PCRE LICENCE + +Please see the file LICENCE in the PCRE distribution for licensing details. + +End diff --git a/src/3rdparty/pcre/LICENCE b/src/3rdparty/pcre/LICENCE new file mode 100644 index 0000000000..5ce31a828d --- /dev/null +++ b/src/3rdparty/pcre/LICENCE @@ -0,0 +1,92 @@ +PCRE LICENCE +------------ + +PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + +Release 8 of PCRE is distributed under the terms of the "BSD" licence, as +specified below. The documentation for PCRE, supplied in the "doc" +directory, is distributed under the same terms as the software itself. + +The basic library functions are written in C and are freestanding. Also +included in the distribution is a set of C++ wrapper functions, and a +just-in-time compiler that can be used to optimize pattern matching. These +are both optional features that can be omitted when the library is built. + + +THE BASIC LIBRARY FUNCTIONS +--------------------------- + +Written by: Philip Hazel +Email local part: ph10 +Email domain: cam.ac.uk + +University of Cambridge Computing Service, +Cambridge, England. + +Copyright (c) 1997-2012 University of Cambridge +All rights reserved. + + +PCRE JUST-IN-TIME COMPILATION SUPPORT +------------------------------------- + +Written by: Zoltan Herczeg +Email local part: hzmester +Emain domain: freemail.hu + +Copyright(c) 2010-2012 Zoltan Herczeg +All rights reserved. + + +STACK-LESS JUST-IN-TIME COMPILER +-------------------------------- + +Written by: Zoltan Herczeg +Email local part: hzmester +Emain domain: freemail.hu + +Copyright(c) 2009-2012 Zoltan Herczeg +All rights reserved. + + +THE C++ WRAPPER FUNCTIONS +------------------------- + +Contributed by: Google Inc. + +Copyright (c) 2007-2012, Google Inc. +All rights reserved. + + +THE "BSD" LICENCE +----------------- + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the name of Google + Inc. nor the names of their contributors may be used to endorse or + promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +End diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h new file mode 100644 index 0000000000..712bd3d714 --- /dev/null +++ b/src/3rdparty/pcre/pcre.h @@ -0,0 +1,503 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* This is the public header file for the PCRE library, to be #included by +applications that call the PCRE functions. + + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +#ifndef _PCRE_H +#define _PCRE_H + +/* The current PCRE version information. */ + +#define PCRE_MAJOR 8 +#define PCRE_MINOR 30 +#define PCRE_PRERELEASE +#define PCRE_DATE 2012-02-04 + +/* 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 +export setting is defined in pcre_internal.h, which includes this file. So we +don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ + +#if defined(_WIN32) && !defined(PCRE_STATIC) +# ifndef PCRE_EXP_DECL +# define PCRE_EXP_DECL extern __declspec(dllimport) +# endif +# ifdef __cplusplus +# ifndef PCRECPP_EXP_DECL +# define PCRECPP_EXP_DECL extern __declspec(dllimport) +# endif +# ifndef PCRECPP_EXP_DEFN +# define PCRECPP_EXP_DEFN __declspec(dllimport) +# endif +# endif +#endif + +/* By default, we use the standard "extern" declarations. */ + +#ifndef PCRE_EXP_DECL +# ifdef __cplusplus +# define PCRE_EXP_DECL extern "C" +# else +# define PCRE_EXP_DECL extern +# endif +#endif + +#ifdef __cplusplus +# ifndef PCRECPP_EXP_DECL +# define PCRECPP_EXP_DECL extern +# endif +# ifndef PCRECPP_EXP_DEFN +# define PCRECPP_EXP_DEFN +# endif +#endif + +/* Have to include stdlib.h in order to ensure that size_t is defined; +it is needed here for malloc. */ + +#include + +/* Allow for C++ users */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Options. Some are compile-time only, some are run-time only, and some are +both, so we keep them all distinct. However, almost all the bits in the options +word are now used. In the long run, we may have to re-use some of the +compile-time only bits for runtime options, or vice versa. In the comments +below, "compile", "exec", and "DFA exec" mean that the option is permitted to +be set for those functions; "used in" means that an option may be set only for +compile, but is subsequently referenced in exec and/or DFA exec. Any of the +compile-time options may be inspected during studying (and therefore JIT +compiling). */ + +#define PCRE_CASELESS 0x00000001 /* Compile */ +#define PCRE_MULTILINE 0x00000002 /* Compile */ +#define PCRE_DOTALL 0x00000004 /* Compile */ +#define PCRE_EXTENDED 0x00000008 /* Compile */ +#define PCRE_ANCHORED 0x00000010 /* Compile, exec, DFA exec */ +#define PCRE_DOLLAR_ENDONLY 0x00000020 /* Compile, used in exec, DFA exec */ +#define PCRE_EXTRA 0x00000040 /* Compile */ +#define PCRE_NOTBOL 0x00000080 /* Exec, DFA exec */ +#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */ +#define PCRE_UNGREEDY 0x00000200 /* Compile */ +#define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */ +/* The next two are also used in exec and DFA exec */ +#define PCRE_UTF8 0x00000800 /* Compile (same as PCRE_UTF16) */ +#define PCRE_UTF16 0x00000800 /* Compile (same as PCRE_UTF8) */ +#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* Compile */ +/* The next two are also used in exec and DFA exec */ +#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF16_CHECK) */ +#define PCRE_NO_UTF16_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF8_CHECK) */ +#define PCRE_AUTO_CALLOUT 0x00004000 /* Compile */ +#define PCRE_PARTIAL_SOFT 0x00008000 /* Exec, DFA exec */ +#define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym */ +#define PCRE_DFA_SHORTEST 0x00010000 /* DFA exec */ +#define PCRE_DFA_RESTART 0x00020000 /* DFA exec */ +#define PCRE_FIRSTLINE 0x00040000 /* Compile, used in exec, DFA exec */ +#define PCRE_DUPNAMES 0x00080000 /* Compile */ +#define PCRE_NEWLINE_CR 0x00100000 /* Compile, exec, DFA exec */ +#define PCRE_NEWLINE_LF 0x00200000 /* Compile, exec, DFA exec */ +#define PCRE_NEWLINE_CRLF 0x00300000 /* Compile, exec, DFA exec */ +#define PCRE_NEWLINE_ANY 0x00400000 /* Compile, exec, DFA exec */ +#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Compile, exec, DFA exec */ +#define PCRE_BSR_ANYCRLF 0x00800000 /* Compile, exec, DFA exec */ +#define PCRE_BSR_UNICODE 0x01000000 /* Compile, exec, DFA exec */ +#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* Compile, used in exec */ +#define PCRE_NO_START_OPTIMIZE 0x04000000 /* Compile, exec, DFA exec */ +#define PCRE_NO_START_OPTIMISE 0x04000000 /* Synonym */ +#define PCRE_PARTIAL_HARD 0x08000000 /* Exec, DFA exec */ +#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* Exec, DFA exec */ +#define PCRE_UCP 0x20000000 /* Compile, used in exec, DFA exec */ + +/* Exec-time and get/set-time error codes */ + +#define PCRE_ERROR_NOMATCH (-1) +#define PCRE_ERROR_NULL (-2) +#define PCRE_ERROR_BADOPTION (-3) +#define PCRE_ERROR_BADMAGIC (-4) +#define PCRE_ERROR_UNKNOWN_OPCODE (-5) +#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ +#define PCRE_ERROR_NOMEMORY (-6) +#define PCRE_ERROR_NOSUBSTRING (-7) +#define PCRE_ERROR_MATCHLIMIT (-8) +#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ +#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16 */ +#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16 */ +#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ +#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ +#define PCRE_ERROR_PARTIAL (-12) +#define PCRE_ERROR_BADPARTIAL (-13) +#define PCRE_ERROR_INTERNAL (-14) +#define PCRE_ERROR_BADCOUNT (-15) +#define PCRE_ERROR_DFA_UITEM (-16) +#define PCRE_ERROR_DFA_UCOND (-17) +#define PCRE_ERROR_DFA_UMLIMIT (-18) +#define PCRE_ERROR_DFA_WSSIZE (-19) +#define PCRE_ERROR_DFA_RECURSE (-20) +#define PCRE_ERROR_RECURSIONLIMIT (-21) +#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ +#define PCRE_ERROR_BADNEWLINE (-23) +#define PCRE_ERROR_BADOFFSET (-24) +#define PCRE_ERROR_SHORTUTF8 (-25) +#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ +#define PCRE_ERROR_RECURSELOOP (-26) +#define PCRE_ERROR_JIT_STACKLIMIT (-27) +#define PCRE_ERROR_BADMODE (-28) +#define PCRE_ERROR_BADENDIANNESS (-29) + +/* Specific error codes for UTF-8 validity checks */ + +#define PCRE_UTF8_ERR0 0 +#define PCRE_UTF8_ERR1 1 +#define PCRE_UTF8_ERR2 2 +#define PCRE_UTF8_ERR3 3 +#define PCRE_UTF8_ERR4 4 +#define PCRE_UTF8_ERR5 5 +#define PCRE_UTF8_ERR6 6 +#define PCRE_UTF8_ERR7 7 +#define PCRE_UTF8_ERR8 8 +#define PCRE_UTF8_ERR9 9 +#define PCRE_UTF8_ERR10 10 +#define PCRE_UTF8_ERR11 11 +#define PCRE_UTF8_ERR12 12 +#define PCRE_UTF8_ERR13 13 +#define PCRE_UTF8_ERR14 14 +#define PCRE_UTF8_ERR15 15 +#define PCRE_UTF8_ERR16 16 +#define PCRE_UTF8_ERR17 17 +#define PCRE_UTF8_ERR18 18 +#define PCRE_UTF8_ERR19 19 +#define PCRE_UTF8_ERR20 20 +#define PCRE_UTF8_ERR21 21 + +/* Specific error codes for UTF-16 validity checks */ + +#define PCRE_UTF16_ERR0 0 +#define PCRE_UTF16_ERR1 1 +#define PCRE_UTF16_ERR2 2 +#define PCRE_UTF16_ERR3 3 +#define PCRE_UTF16_ERR4 4 + +/* Request types for pcre_fullinfo() */ + +#define PCRE_INFO_OPTIONS 0 +#define PCRE_INFO_SIZE 1 +#define PCRE_INFO_CAPTURECOUNT 2 +#define PCRE_INFO_BACKREFMAX 3 +#define PCRE_INFO_FIRSTBYTE 4 +#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ +#define PCRE_INFO_FIRSTTABLE 5 +#define PCRE_INFO_LASTLITERAL 6 +#define PCRE_INFO_NAMEENTRYSIZE 7 +#define PCRE_INFO_NAMECOUNT 8 +#define PCRE_INFO_NAMETABLE 9 +#define PCRE_INFO_STUDYSIZE 10 +#define PCRE_INFO_DEFAULT_TABLES 11 +#define PCRE_INFO_OKPARTIAL 12 +#define PCRE_INFO_JCHANGED 13 +#define PCRE_INFO_HASCRORLF 14 +#define PCRE_INFO_MINLENGTH 15 +#define PCRE_INFO_JIT 16 +#define PCRE_INFO_JITSIZE 17 + +/* Request types for pcre_config(). Do not re-arrange, in order to remain +compatible. */ + +#define PCRE_CONFIG_UTF8 0 +#define PCRE_CONFIG_NEWLINE 1 +#define PCRE_CONFIG_LINK_SIZE 2 +#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 +#define PCRE_CONFIG_MATCH_LIMIT 4 +#define PCRE_CONFIG_STACKRECURSE 5 +#define PCRE_CONFIG_UNICODE_PROPERTIES 6 +#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 +#define PCRE_CONFIG_BSR 8 +#define PCRE_CONFIG_JIT 9 +#define PCRE_CONFIG_UTF16 10 +#define PCRE_CONFIG_JITTARGET 11 + +/* Request types for pcre_study(). Do not re-arrange, in order to remain +compatible. */ + +#define PCRE_STUDY_JIT_COMPILE 0x0001 + +/* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefine +these bits, just add new ones on the end, in order to remain compatible. */ + +#define PCRE_EXTRA_STUDY_DATA 0x0001 +#define PCRE_EXTRA_MATCH_LIMIT 0x0002 +#define PCRE_EXTRA_CALLOUT_DATA 0x0004 +#define PCRE_EXTRA_TABLES 0x0008 +#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 +#define PCRE_EXTRA_MARK 0x0020 +#define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 + +/* Types */ + +struct real_pcre; /* declaration; the definition is private */ +typedef struct real_pcre pcre; + +struct real_pcre16; /* declaration; the definition is private */ +typedef struct real_pcre16 pcre16; + +struct real_pcre_jit_stack; /* declaration; the definition is private */ +typedef struct real_pcre_jit_stack pcre_jit_stack; + +struct real_pcre16_jit_stack; /* declaration; the definition is private */ +typedef struct real_pcre16_jit_stack pcre16_jit_stack; + +/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain +a 16 bit wide signed data type. Otherwise it can be a dummy data type since +pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */ +#ifndef PCRE_UCHAR16 +#define PCRE_UCHAR16 unsigned short +#endif + +#ifndef PCRE_SPTR16 +#define PCRE_SPTR16 const PCRE_UCHAR16 * +#endif + +/* When PCRE is compiled as a C++ library, the subject pointer type can be +replaced with a custom type. For conventional use, the public interface is a +const char *. */ + +#ifndef PCRE_SPTR +#define PCRE_SPTR const char * +#endif + +/* The structure for passing additional data to pcre_exec(). This is defined in +such as way as to be extensible. Always add new fields at the end, in order to +remain compatible. */ + +typedef struct pcre_extra { + unsigned long int flags; /* Bits for which fields are set */ + void *study_data; /* Opaque data from pcre_study() */ + unsigned long int match_limit; /* Maximum number of calls to match() */ + void *callout_data; /* Data passed back in callouts */ + const unsigned char *tables; /* Pointer to character tables */ + unsigned long int match_limit_recursion; /* Max recursive calls to match() */ + unsigned char **mark; /* For passing back a mark pointer */ + void *executable_jit; /* Contains a pointer to a compiled jit code */ +} pcre_extra; + +/* Same structure as above, but with 16 bit char pointers. */ + +typedef struct pcre16_extra { + unsigned long int flags; /* Bits for which fields are set */ + void *study_data; /* Opaque data from pcre_study() */ + unsigned long int match_limit; /* Maximum number of calls to match() */ + void *callout_data; /* Data passed back in callouts */ + const unsigned char *tables; /* Pointer to character tables */ + unsigned long int match_limit_recursion; /* Max recursive calls to match() */ + PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ + void *executable_jit; /* Contains a pointer to a compiled jit code */ +} pcre16_extra; + +/* The structure for passing out data via the pcre_callout_function. We use a +structure so that new fields can be added on the end in future versions, +without changing the API of the function, thereby allowing old clients to work +without modification. */ + +typedef struct pcre_callout_block { + int version; /* Identifies version of block */ + /* ------------------------ Version 0 ------------------------------- */ + int callout_number; /* Number compiled into pattern */ + int *offset_vector; /* The offset vector */ + PCRE_SPTR subject; /* The subject being matched */ + int subject_length; /* The length of the subject */ + int start_match; /* Offset to start of this match attempt */ + int current_position; /* Where we currently are in the subject */ + int capture_top; /* Max current capture */ + int capture_last; /* Most recently closed capture */ + void *callout_data; /* Data passed in with the call */ + /* ------------------- Added for Version 1 -------------------------- */ + int pattern_position; /* Offset to next item in the pattern */ + int next_item_length; /* Length of next item in the pattern */ + /* ------------------- Added for Version 2 -------------------------- */ + const unsigned char *mark; /* Pointer to current mark or NULL */ + /* ------------------------------------------------------------------ */ +} pcre_callout_block; + +/* Same structure as above, but with 16 bit char pointers. */ + +typedef struct pcre16_callout_block { + int version; /* Identifies version of block */ + /* ------------------------ Version 0 ------------------------------- */ + int callout_number; /* Number compiled into pattern */ + int *offset_vector; /* The offset vector */ + PCRE_SPTR16 subject; /* The subject being matched */ + int subject_length; /* The length of the subject */ + int start_match; /* Offset to start of this match attempt */ + int current_position; /* Where we currently are in the subject */ + int capture_top; /* Max current capture */ + int capture_last; /* Most recently closed capture */ + void *callout_data; /* Data passed in with the call */ + /* ------------------- Added for Version 1 -------------------------- */ + int pattern_position; /* Offset to next item in the pattern */ + int next_item_length; /* Length of next item in the pattern */ + /* ------------------- Added for Version 2 -------------------------- */ + const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ + /* ------------------------------------------------------------------ */ +} pcre16_callout_block; + +/* Indirection for store get and free functions. These can be set to +alternative malloc/free functions if required. Special ones are used in the +non-recursive case for "frames". There is also an optional callout function +that is triggered by the (?) regex item. For Virtual Pascal, these definitions +have to take another form. */ + +#ifndef VPCOMPAT +PCRE_EXP_DECL void *(*pcre_malloc)(size_t); +PCRE_EXP_DECL void (*pcre_free)(void *); +PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); +PCRE_EXP_DECL void (*pcre_stack_free)(void *); +PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); + +PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); +PCRE_EXP_DECL void (*pcre16_free)(void *); +PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); +PCRE_EXP_DECL void (*pcre16_stack_free)(void *); +PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); +#else /* VPCOMPAT */ +PCRE_EXP_DECL void *pcre_malloc(size_t); +PCRE_EXP_DECL void pcre_free(void *); +PCRE_EXP_DECL void *pcre_stack_malloc(size_t); +PCRE_EXP_DECL void pcre_stack_free(void *); +PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); + +PCRE_EXP_DECL void *pcre16_malloc(size_t); +PCRE_EXP_DECL void pcre16_free(void *); +PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); +PCRE_EXP_DECL void pcre16_stack_free(void *); +PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); +#endif /* VPCOMPAT */ + +/* User defined callback which provides a stack just before the match starts. */ + +typedef pcre_jit_stack *(*pcre_jit_callback)(void *); +typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); + +/* Exported PCRE functions */ + +PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, + const unsigned char *); +PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *, + const unsigned char *); +PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, + int *, const unsigned char *); +PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **, + int *, const unsigned char *); +PCRE_EXP_DECL int pcre_config(int, void *); +PCRE_EXP_DECL int pcre16_config(int, void *); +PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, + int *, int, const char *, char *, int); +PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, + int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); +PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, + char *, int); +PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, + PCRE_UCHAR16 *, int); +PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, + const char *, int, int, int, int *, int , int *, int); +PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, + PCRE_SPTR16, int, int, int, int *, int , int *, int); +PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, + int, int, int, int *, int); +PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, + PCRE_SPTR16, int, int, int, int *, int); +PCRE_EXP_DECL void pcre_free_substring(const char *); +PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); +PCRE_EXP_DECL void pcre_free_substring_list(const char **); +PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); +PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, + void *); +PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int, + void *); +PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, + int *, int, const char *, const char **); +PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, + int *, int, PCRE_SPTR16, PCRE_SPTR16 *); +PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); +PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); +PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, + char **, char **); +PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16, + PCRE_UCHAR16 **, PCRE_UCHAR16 **); +PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, + const char **); +PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, + PCRE_SPTR16 *); +PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, + const char ***); +PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, + PCRE_SPTR16 **); +PCRE_EXP_DECL const unsigned char *pcre_maketables(void); +PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); +PCRE_EXP_DECL int pcre_refcount(pcre *, int); +PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); +PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); +PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **); +PCRE_EXP_DECL void pcre_free_study(pcre_extra *); +PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); +PCRE_EXP_DECL const char *pcre_version(void); +PCRE_EXP_DECL const char *pcre16_version(void); + +/* Utility functions for byte order swaps. */ +PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, + const unsigned char *); +PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, + const unsigned char *); +PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, + PCRE_SPTR16, int, int *, int); + +/* JIT compiler related functions. */ + +PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); +PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); +PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); +PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); +PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, + pcre_jit_callback, void *); +PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, + pcre16_jit_callback, void *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* End of pcre.h */ diff --git a/src/3rdparty/pcre/pcre16_byte_order.c b/src/3rdparty/pcre/pcre16_byte_order.c new file mode 100644 index 0000000000..11d2973a3d --- /dev/null +++ b/src/3rdparty/pcre/pcre16_byte_order.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_byte_order.c" + +/* End of pcre16_byte_order.c */ diff --git a/src/3rdparty/pcre/pcre16_chartables.c b/src/3rdparty/pcre/pcre16_chartables.c new file mode 100644 index 0000000000..7c0ff35f5e --- /dev/null +++ b/src/3rdparty/pcre/pcre16_chartables.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_chartables.c" + +/* End of pcre16_chartables.c */ diff --git a/src/3rdparty/pcre/pcre16_compile.c b/src/3rdparty/pcre/pcre16_compile.c new file mode 100644 index 0000000000..e499b67087 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_compile.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_compile.c" + +/* End of pcre16_compile.c */ diff --git a/src/3rdparty/pcre/pcre16_config.c b/src/3rdparty/pcre/pcre16_config.c new file mode 100644 index 0000000000..b52138764f --- /dev/null +++ b/src/3rdparty/pcre/pcre16_config.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_config.c" + +/* End of pcre16_config.c */ diff --git a/src/3rdparty/pcre/pcre16_dfa_exec.c b/src/3rdparty/pcre/pcre16_dfa_exec.c new file mode 100644 index 0000000000..2ba740e972 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_dfa_exec.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_dfa_exec.c" + +/* End of pcre16_dfa_exec.c */ diff --git a/src/3rdparty/pcre/pcre16_exec.c b/src/3rdparty/pcre/pcre16_exec.c new file mode 100644 index 0000000000..7417b1770c --- /dev/null +++ b/src/3rdparty/pcre/pcre16_exec.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_exec.c" + +/* End of pcre16_exec.c */ diff --git a/src/3rdparty/pcre/pcre16_fullinfo.c b/src/3rdparty/pcre/pcre16_fullinfo.c new file mode 100644 index 0000000000..544dca6ed5 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_fullinfo.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_fullinfo.c" + +/* End of pcre16_fullinfo.c */ diff --git a/src/3rdparty/pcre/pcre16_get.c b/src/3rdparty/pcre/pcre16_get.c new file mode 100644 index 0000000000..3ded08c622 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_get.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_get.c" + +/* End of pcre16_get.c */ diff --git a/src/3rdparty/pcre/pcre16_globals.c b/src/3rdparty/pcre/pcre16_globals.c new file mode 100644 index 0000000000..a136b3d8c2 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_globals.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_globals.c" + +/* End of pcre16_globals.c */ diff --git a/src/3rdparty/pcre/pcre16_jit_compile.c b/src/3rdparty/pcre/pcre16_jit_compile.c new file mode 100644 index 0000000000..ab0cacd764 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_jit_compile.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_jit_compile.c" + +/* End of pcre16_jit_compile.c */ diff --git a/src/3rdparty/pcre/pcre16_maketables.c b/src/3rdparty/pcre/pcre16_maketables.c new file mode 100644 index 0000000000..b1cd1c579d --- /dev/null +++ b/src/3rdparty/pcre/pcre16_maketables.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_maketables.c" + +/* End of pcre16_maketables.c */ diff --git a/src/3rdparty/pcre/pcre16_newline.c b/src/3rdparty/pcre/pcre16_newline.c new file mode 100644 index 0000000000..7fe201400f --- /dev/null +++ b/src/3rdparty/pcre/pcre16_newline.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_newline.c" + +/* End of pcre16_newline.c */ diff --git a/src/3rdparty/pcre/pcre16_ord2utf16.c b/src/3rdparty/pcre/pcre16_ord2utf16.c new file mode 100644 index 0000000000..9f7db8661f --- /dev/null +++ b/src/3rdparty/pcre/pcre16_ord2utf16.c @@ -0,0 +1,95 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This file contains a private PCRE function that converts an ordinal +character value into a UTF16 string. */ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_internal.h" + +/************************************************* +* Convert character value to UTF-16 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x10ffff +and encodes it as a UTF-16 character in 1 to 2 pcre_uchars. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 2 pcre_uchars long + +Returns: number of characters placed in the buffer +*/ + +int +PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) +{ +#ifdef SUPPORT_UTF + +/* Checking invalid cvalue character, encoded as invalid UTF-16 character. +Should never happen in practice. */ +if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000) + cvalue = 0xfffe; + +if (cvalue <= 0xffff) + { + *buffer = (pcre_uchar)cvalue; + return 1; + } + +cvalue -= 0x10000; +*buffer++ = 0xd800 | (cvalue >> 10); +*buffer = 0xdc00 | (cvalue & 0x3ff); +return 2; + +#else /* SUPPORT_UTF */ +(void)(cvalue); /* Keep compiler happy; this function won't ever be */ +(void)(buffer); /* called when SUPPORT_UTF is not defined. */ +return 0; +#endif /* SUPPORT_UTF */ +} + +/* End of pcre16_ord2utf16.c */ diff --git a/src/3rdparty/pcre/pcre16_refcount.c b/src/3rdparty/pcre/pcre16_refcount.c new file mode 100644 index 0000000000..d3d1543973 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_refcount.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_refcount.c" + +/* End of pcre16_refcount.c */ diff --git a/src/3rdparty/pcre/pcre16_string_utils.c b/src/3rdparty/pcre/pcre16_string_utils.c new file mode 100644 index 0000000000..382c40799f --- /dev/null +++ b/src/3rdparty/pcre/pcre16_string_utils.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_string_utils.c" + +/* End of pcre16_string_utils.c */ diff --git a/src/3rdparty/pcre/pcre16_study.c b/src/3rdparty/pcre/pcre16_study.c new file mode 100644 index 0000000000..f87de081fc --- /dev/null +++ b/src/3rdparty/pcre/pcre16_study.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_study.c" + +/* End of pcre16_study.c */ diff --git a/src/3rdparty/pcre/pcre16_tables.c b/src/3rdparty/pcre/pcre16_tables.c new file mode 100644 index 0000000000..d84297093a --- /dev/null +++ b/src/3rdparty/pcre/pcre16_tables.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_tables.c" + +/* End of pcre16_tables.c */ diff --git a/src/3rdparty/pcre/pcre16_ucd.c b/src/3rdparty/pcre/pcre16_ucd.c new file mode 100644 index 0000000000..ee23439a01 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_ucd.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_ucd.c" + +/* End of pcre16_ucd.c */ diff --git a/src/3rdparty/pcre/pcre16_utf16_utils.c b/src/3rdparty/pcre/pcre16_utf16_utils.c new file mode 100644 index 0000000000..7cfdbdd5ee --- /dev/null +++ b/src/3rdparty/pcre/pcre16_utf16_utils.c @@ -0,0 +1,129 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains a function for converting any UTF-16 character +strings to host byte order. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_internal.h" + +/************************************************* +* Convert any UTF-16 string to host byte order * +*************************************************/ + +/* This function takes an UTF-16 string and converts +it to host byte order. The length can be explicitly set, +or automatically detected for zero terminated strings. +BOMs can be kept or discarded during the conversion. +Conversion can be done in place (output == input). + +Arguments: + output the output buffer, its size must be greater + or equal than the input string + input any UTF-16 string + length the number of 16-bit units in the input string + can be less than zero for zero terminated strings + host_byte_order + A non-zero value means the input is in host byte + order, which can be dynamically changed by BOMs later. + Initially it contains the starting byte order and returns + with the last byte order so it can be used for stream + processing. It can be NULL, which set the host byte + order mode by default. + keep_boms for a non-zero value, the BOM (0xfeff) characters + are copied as well + +Returns: the number of 16-bit units placed into the output buffer, + including the zero-terminator +*/ + +int +pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *output, PCRE_SPTR16 input, + int length, int *host_byte_order, int keep_boms) +{ +#ifdef SUPPORT_UTF +/* This function converts any UTF-16 string to host byte order and optionally +removes any Byte Order Marks (BOMS). Returns with the remainig length. */ +int host_bo = host_byte_order != NULL ? *host_byte_order : 1; +pcre_uchar *optr = (pcre_uchar *)output; +const pcre_uchar *iptr = (const pcre_uchar *)input; +const pcre_uchar *end; +/* The c variable must be unsigned. */ +register pcre_uchar c; + +if (length < 0) + length = STRLEN_UC(iptr) + 1; +end = iptr + length; + +while (iptr < end) + { + c = *iptr++; + if (c == 0xfeff || c == 0xfffe) + { + /* Detecting the byte order of the machine is unnecessary, it is + enough to know that the UTF-16 string has the same byte order or not. */ + host_bo = c == 0xfeff; + if (keep_boms != 0) + *optr++ = 0xfeff; + else + length--; + } + else + *optr++ = host_bo ? c : ((c >> 8) | (c << 8)); /* Flip bytes if needed. */ + } +if (host_byte_order != NULL) + *host_byte_order = host_bo; + +#else /* SUPPORT_UTF */ +(void)(output); /* Keep picky compilers happy */ +(void)(input); +(void)(keep_boms); +#endif /* SUPPORT_UTF */ +return length; +} + +/* End of pcre16_utf16_utils.c */ diff --git a/src/3rdparty/pcre/pcre16_valid_utf16.c b/src/3rdparty/pcre/pcre16_valid_utf16.c new file mode 100644 index 0000000000..90b9f86770 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_valid_utf16.c @@ -0,0 +1,146 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function for validating UTF-16 character +strings. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_internal.h" + + +/************************************************* +* Validate a UTF-16 string * +*************************************************/ + +/* This function is called (optionally) at the start of compile or match, to +check that a supposed UTF-16 string is actually valid. The early check means +that subsequent code can assume it is dealing with a valid string. The check +can be turned off for maximum performance, but the consequences of supplying an +invalid string are then undefined. + +From release 8.21 more information about the details of the error are passed +back in the returned value: + +PCRE_UTF16_ERR0 No error +PCRE_UTF16_ERR1 Missing low surrogate at the end of the string +PCRE_UTF16_ERR2 Invalid low surrogate +PCRE_UTF16_ERR3 Isolated low surrogate +PCRE_UTF16_ERR4 Not allowed character + +Arguments: + string points to the string + length length of string, or -1 if the string is zero-terminated + errp pointer to an error position offset variable + +Returns: = 0 if the string is a valid UTF-16 string + > 0 otherwise, setting the offset of the bad character +*/ + +int +PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) +{ +#ifdef SUPPORT_UTF +register PCRE_PUCHAR p; +register pcre_uchar c; + +if (length < 0) + { + for (p = string; *p != 0; p++); + length = p - string; + } + +for (p = string; length-- > 0; p++) + { + c = *p; + + if ((c & 0xf800) != 0xd800) + { + /* Normal UTF-16 code point. Neither high nor low surrogate. */ + + /* This is probably a BOM from a different byte-order. + Regardless, the string is rejected. */ + if (c == 0xfffe) + { + *erroroffset = p - string; + return PCRE_UTF16_ERR4; + } + } + else if ((c & 0x0400) == 0) + { + /* High surrogate. */ + + /* Must be a followed by a low surrogate. */ + if (length == 0) + { + *erroroffset = p - string; + return PCRE_UTF16_ERR1; + } + p++; + length--; + if ((*p & 0xfc00) != 0xdc00) + { + *erroroffset = p - string; + return PCRE_UTF16_ERR2; + } + } + else + { + /* Isolated low surrogate. Always an error. */ + *erroroffset = p - string; + return PCRE_UTF16_ERR3; + } + } + +#else /* SUPPORT_UTF */ +(void)(string); /* Keep picky compilers happy */ +(void)(length); +#endif /* SUPPORT_UTF */ + +return PCRE_UTF16_ERR0; /* This indicates success */ +} + +/* End of pcre16_valid_utf16.c */ diff --git a/src/3rdparty/pcre/pcre16_version.c b/src/3rdparty/pcre/pcre16_version.c new file mode 100644 index 0000000000..e991b1a8cf --- /dev/null +++ b/src/3rdparty/pcre/pcre16_version.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_version.c" + +/* End of pcre16_version.c */ diff --git a/src/3rdparty/pcre/pcre16_xclass.c b/src/3rdparty/pcre/pcre16_xclass.c new file mode 100644 index 0000000000..5aac2a36c6 --- /dev/null +++ b/src/3rdparty/pcre/pcre16_xclass.c @@ -0,0 +1,45 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* Generate code with 16 bit character support. */ +#define COMPILE_PCRE16 + +#include "pcre_xclass.c" + +/* End of pcre16_xclass.c */ diff --git a/src/3rdparty/pcre/pcre_byte_order.c b/src/3rdparty/pcre/pcre_byte_order.c new file mode 100644 index 0000000000..6f5fa742d6 --- /dev/null +++ b/src/3rdparty/pcre/pcre_byte_order.c @@ -0,0 +1,288 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that tests a compiled pattern to +see if it was compiled with the opposite endianness. If so, it uses an +auxiliary local function to flip the appropriate bytes. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Swap byte functions * +*************************************************/ + +/* The following functions swap the bytes of a pcre_uint16 +and pcre_uint32 value. + +Arguments: + value any number + +Returns: the byte swapped value +*/ + +static pcre_uint32 +swap_uint32(pcre_uint32 value) +{ +return ((value & 0x000000ff) << 24) | + ((value & 0x0000ff00) << 8) | + ((value & 0x00ff0000) >> 8) | + (value >> 24); +} + +static pcre_uint16 +swap_uint16(pcre_uint16 value) +{ +return (value >> 8) | (value << 8); +} + + +/************************************************* +* Test for a byte-flipped compiled regex * +*************************************************/ + +/* This function swaps the bytes of a compiled pattern usually +loaded form the disk. It also sets the tables pointer, which +is likely an invalid pointer after reload. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL + tables points to the character tables or NULL + +Returns: 0 if the swap is successful, negative on error +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re, + pcre_extra *extra_data, const unsigned char *tables) +#else +PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re, + pcre16_extra *extra_data, const unsigned char *tables) +#endif +{ +REAL_PCRE *re = (REAL_PCRE *)argument_re; +pcre_study_data *study; +#ifndef COMPILE_PCRE8 +pcre_uchar *ptr; +int length; +#ifdef SUPPORT_UTF +BOOL utf; +BOOL utf16_char; +#endif /* SUPPORT_UTF */ +#endif /* !COMPILE_PCRE8 */ + +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number == MAGIC_NUMBER) + { + if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; + re->tables = tables; + return 0; + } + +if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; +if ((swap_uint16(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; + +re->magic_number = MAGIC_NUMBER; +re->size = swap_uint32(re->size); +re->options = swap_uint32(re->options); +re->flags = swap_uint16(re->flags); +re->top_bracket = swap_uint16(re->top_bracket); +re->top_backref = swap_uint16(re->top_backref); +re->first_char = swap_uint16(re->first_char); +re->req_char = swap_uint16(re->req_char); +re->name_table_offset = swap_uint16(re->name_table_offset); +re->name_entry_size = swap_uint16(re->name_entry_size); +re->name_count = swap_uint16(re->name_count); +re->ref_count = swap_uint16(re->ref_count); +re->tables = tables; + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) + { + study = (pcre_study_data *)extra_data->study_data; + study->size = swap_uint32(study->size); + study->flags = swap_uint32(study->flags); + study->minlength = swap_uint32(study->minlength); + } + +#ifndef COMPILE_PCRE8 +ptr = (pcre_uchar *)re + re->name_table_offset; +length = re->name_count * re->name_entry_size; +#ifdef SUPPORT_UTF +utf = (re->options & PCRE_UTF16) != 0; +utf16_char = FALSE; +#endif + +while(TRUE) + { + /* Swap previous characters. */ + while (length-- > 0) + { + *ptr = swap_uint16(*ptr); + ptr++; + } +#ifdef SUPPORT_UTF + if (utf16_char) + { + if (HAS_EXTRALEN(ptr[-1])) + { + /* We know that there is only one extra character in UTF-16. */ + *ptr = swap_uint16(*ptr); + ptr++; + } + } + utf16_char = FALSE; +#endif /* SUPPORT_UTF */ + + /* Get next opcode. */ + length = 0; + *ptr = swap_uint16(*ptr); + switch (*ptr) + { + case OP_END: + return 0; + +#ifdef SUPPORT_UTF + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + case OP_EXACT: + case OP_POSSTAR: + case OP_POSPLUS: + case OP_POSQUERY: + case OP_POSUPTO: + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_UPTOI: + case OP_MINUPTOI: + case OP_EXACTI: + case OP_POSSTARI: + case OP_POSPLUSI: + case OP_POSQUERYI: + case OP_POSUPTOI: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTEXACT: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + case OP_NOTPOSQUERY: + case OP_NOTPOSUPTO: + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTEXACTI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERYI: + case OP_NOTPOSUPTOI: + if (utf) utf16_char = TRUE; +#endif + /* Fall through. */ + + default: + length = PRIV(OP_lengths)[*ptr] - 1; + break; + + case OP_CLASS: + case OP_NCLASS: + /* Skip the character bit map. */ + ptr += 32/sizeof(pcre_uchar); + length = 0; + break; + + case OP_XCLASS: + /* Reverse the size of the XCLASS instance. */ + ptr++; + *ptr = swap_uint16(*ptr); + if (LINK_SIZE > 1) + { + /* LINK_SIZE can be 1 or 2 in 16 bit mode. */ + ptr++; + *ptr = swap_uint16(*ptr); + } + ptr++; + length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1); + *ptr = swap_uint16(*ptr); + if ((*ptr & XCL_MAP) != 0) + { + /* Skip the character bit map. */ + ptr += 32/sizeof(pcre_uchar); + length -= 32/sizeof(pcre_uchar); + } + break; + } + ptr++; + } +/* Control should never reach here in 16 bit mode. */ +#endif /* !COMPILE_PCRE8 */ + +return 0; +} + +/* End of pcre_byte_order.c */ diff --git a/src/3rdparty/pcre/pcre_chartables.c b/src/3rdparty/pcre/pcre_chartables.c new file mode 100644 index 0000000000..55df49777d --- /dev/null +++ b/src/3rdparty/pcre/pcre_chartables.c @@ -0,0 +1,198 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* This file contains character tables that are used when no external tables +are passed to PCRE by the application that calls it. The tables are used only +for characters whose code values are less than 256. + +This is a default version of the tables that assumes ASCII encoding. A program +called dftables (which is distributed with PCRE) can be used to build +alternative versions of this file. This is necessary if you are running in an +EBCDIC environment, or if you want to default to a different encoding, for +example ISO-8859-1. When dftables is run, it creates these tables in the +current locale. If PCRE is configured with --enable-rebuild-chartables, this +happens automatically. + +The following #includes are present because without them gcc 4.x may remove the +array definition from the final binary if PCRE is built into a static library +and dead code stripping is activated. This leads to link errors. Pulling in the +header ensures that the array gets flagged as "someone outside this compilation +unit might reference this" and so it will always be supplied to the linker. */ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +const pcre_uint8 PRIV(default_tables)[] = { + +/* This table is a lower casing table. */ + + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122, 91, 92, 93, 94, 95, + 96, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167, + 168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183, + 184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215, + 216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231, + 232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,255, + +/* This table is a case flipping table. */ + + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 97, 98, 99,100,101,102,103, + 104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119, + 120,121,122, 91, 92, 93, 94, 95, + 96, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90,123,124,125,126,127, + 128,129,130,131,132,133,134,135, + 136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151, + 152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167, + 168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183, + 184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199, + 200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215, + 216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231, + 232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247, + 248,249,250,251,252,253,254,255, + +/* This table contains bit maps for various character classes. Each map is 32 +bytes long and the bits run from the least significant end of each byte. The +classes that have their own maps are: space, xdigit, digit, upper, lower, word, +graph, print, punct, and cntrl. Other classes are built from combinations. */ + + 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, + 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +/* This table identifies various classes of character by individual bits: + 0x01 white space character + 0x02 letter + 0x04 decimal digit + 0x08 hexadecimal digit + 0x10 alphanumeric or '_' + 0x80 regular expression metacharacter or binary zero +*/ + + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */ + 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */ + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */ + 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */ + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */ + 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +/* End of pcre_chartables.c */ diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c new file mode 100644 index 0000000000..b0c57ca122 --- /dev/null +++ b/src/3rdparty/pcre/pcre_compile.c @@ -0,0 +1,8162 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_compile(), along with +supporting internal functions that are not used by other modules. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK cd /* Block containing newline information */ +#define PSSTART start_pattern /* Field containing processed string start */ +#define PSEND end_pattern /* Field containing processed string end */ + +#include "pcre_internal.h" + + +/* When PCRE_DEBUG is defined, we need the pcre(16)_printint() function, which +is also used by pcretest. PCRE_DEBUG is not defined when building a production +library. We do not need to select pcre16_printint.c specially, because the +COMPILE_PCREx macro will already be appropriately set. */ + +#ifdef PCRE_DEBUG +/* pcre_printint.c should not include any headers */ +#define PCRE_INCLUDED +#include "pcre_printint.c" +#undef PCRE_INCLUDED +#endif + + +/* Macro for setting individual bits in class bitmaps. */ + +#define SETBIT(a,b) a[b/8] |= (1 << (b%8)) + +/* Maximum length value to check against when making sure that the integer that +holds the compiled pattern length does not overflow. We make it a bit less than +INT_MAX to allow for adding in group terminating bytes, so that we don't have +to check them every time. */ + +#define OFLOW_MAX (INT_MAX - 20) + + +/************************************************* +* Code parameters and static tables * +*************************************************/ + +/* This value specifies the size of stack workspace that is used during the +first pre-compile phase that determines how much memory is required. The regex +is partly compiled into this space, but the compiled parts are discarded as +soon as they can be, so that hopefully there will never be an overrun. The code +does, however, check for an overrun. The largest amount I've seen used is 218, +so this number is very generous. + +The same workspace is used during the second, actual compile phase for +remembering forward references to groups so that they can be filled in at the +end. Each entry in this list occupies LINK_SIZE bytes, so even when LINK_SIZE +is 4 there is plenty of room for most patterns. However, the memory can get +filled up by repetitions of forward references, for example patterns like +/(?1){0,1999}(b)/, and one user did hit the limit. The code has been changed so +that the workspace is expanded using malloc() in this situation. The value +below is therefore a minimum, and we put a maximum on it for safety. The +minimum is now also defined in terms of LINK_SIZE so that the use of malloc() +kicks in at the same number of forward references in all cases. */ + +#define COMPILE_WORK_SIZE (2048*LINK_SIZE) +#define COMPILE_WORK_SIZE_MAX (100*COMPILE_WORK_SIZE) + +/* The overrun tests check for a slightly smaller size so that they detect the +overrun before it actually does run off the end of the data block. */ + +#define WORK_SIZE_SAFETY_MARGIN (100) + +/* Private flags added to firstchar and reqchar. */ + +#define REQ_CASELESS 0x10000000l /* Indicates caselessness */ +#define REQ_VARY 0x20000000l /* Reqchar followed non-literal item */ + +/* Repeated character flags. */ + +#define UTF_LENGTH 0x10000000l /* The char contains its length. */ + +/* Table for handling escaped characters in the range '0'-'z'. Positive returns +are simple data values; negative values are for special things like \d and so +on. Zero means further processing is needed (for things like \x), or the escape +is invalid. */ + +#ifndef EBCDIC + +/* This is the "normal" table for ASCII systems or for EBCDIC systems running +in UTF-8 mode. */ + +static const short int escapes[] = { + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + CHAR_COLON, CHAR_SEMICOLON, + CHAR_LESS_THAN_SIGN, CHAR_EQUALS_SIGN, + CHAR_GREATER_THAN_SIGN, CHAR_QUESTION_MARK, + CHAR_COMMERCIAL_AT, -ESC_A, + -ESC_B, -ESC_C, + -ESC_D, -ESC_E, + 0, -ESC_G, + -ESC_H, 0, + 0, -ESC_K, + 0, 0, + -ESC_N, 0, + -ESC_P, -ESC_Q, + -ESC_R, -ESC_S, + 0, 0, + -ESC_V, -ESC_W, + -ESC_X, 0, + -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, + CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, + CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, + CHAR_GRAVE_ACCENT, 7, + -ESC_b, 0, + -ESC_d, ESC_e, + ESC_f, 0, + -ESC_h, 0, + 0, -ESC_k, + 0, 0, + ESC_n, 0, + -ESC_p, 0, + ESC_r, -ESC_s, + ESC_tee, 0, + -ESC_v, -ESC_w, + 0, 0, + -ESC_z +}; + +#else + +/* This is the "abnormal" table for EBCDIC systems without UTF-8 support. */ + +static const short int escapes[] = { +/* 48 */ 0, 0, 0, '.', '<', '(', '+', '|', +/* 50 */ '&', 0, 0, 0, 0, 0, 0, 0, +/* 58 */ 0, 0, '!', '$', '*', ')', ';', '~', +/* 60 */ '-', '/', 0, 0, 0, 0, 0, 0, +/* 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, +/* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, +/* 90 */ 0, 0, -ESC_k, 'l', 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, +/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-', +/* C0 */ '{',-ESC_A, -ESC_B, -ESC_C, -ESC_D,-ESC_E, 0, -ESC_G, +/* C8 */-ESC_H, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ '}', 0, -ESC_K, 0, 0,-ESC_N, 0, -ESC_P, +/* D8 */-ESC_Q,-ESC_R, 0, 0, 0, 0, 0, 0, +/* E0 */ '\\', 0, -ESC_S, 0, 0,-ESC_V, -ESC_W, -ESC_X, +/* E8 */ 0,-ESC_Z, 0, 0, 0, 0, 0, 0, +/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 +}; +#endif + + +/* Table of special "verbs" like (*PRUNE). This is a short table, so it is +searched linearly. Put all the names into a single string, in order to reduce +the number of relocations when a shared library is dynamically linked. The +string is built from string macros so that it works in UTF-8 mode on EBCDIC +platforms. */ + +typedef struct verbitem { + int len; /* Length of verb name */ + int op; /* Op when no arg, or -1 if arg mandatory */ + int op_arg; /* Op when arg present, or -1 if not allowed */ +} verbitem; + +static const char verbnames[] = + "\0" /* Empty name is a shorthand for MARK */ + STRING_MARK0 + STRING_ACCEPT0 + STRING_COMMIT0 + STRING_F0 + STRING_FAIL0 + STRING_PRUNE0 + STRING_SKIP0 + STRING_THEN; + +static const verbitem verbs[] = { + { 0, -1, OP_MARK }, + { 4, -1, OP_MARK }, + { 6, OP_ACCEPT, -1 }, + { 6, OP_COMMIT, -1 }, + { 1, OP_FAIL, -1 }, + { 4, OP_FAIL, -1 }, + { 5, OP_PRUNE, OP_PRUNE_ARG }, + { 4, OP_SKIP, OP_SKIP_ARG }, + { 4, OP_THEN, OP_THEN_ARG } +}; + +static const int verbcount = sizeof(verbs)/sizeof(verbitem); + + +/* Tables of names of POSIX character classes and their lengths. The names are +now all in a single string, to reduce the number of relocations when a shared +library is dynamically loaded. The list of lengths is terminated by a zero +length entry. The first three must be alpha, lower, upper, as this is assumed +for handling case independence. */ + +static const char posix_names[] = + STRING_alpha0 STRING_lower0 STRING_upper0 STRING_alnum0 + STRING_ascii0 STRING_blank0 STRING_cntrl0 STRING_digit0 + STRING_graph0 STRING_print0 STRING_punct0 STRING_space0 + STRING_word0 STRING_xdigit; + +static const pcre_uint8 posix_name_lengths[] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 6, 0 }; + +/* Table of class bit maps for each POSIX class. Each class is formed from a +base map, with an optional addition or removal of another map. Then, for some +classes, there is some additional tweaking: for [:blank:] the vertical space +characters are removed, and for [:alpha:] and [:alnum:] the underscore +character is removed. The triples in the table consist of the base map offset, +second map offset or -1 if no second map, and a non-negative value for map +addition or a negative value for map subtraction (if there are two maps). The +absolute value of the third field has these meanings: 0 => no tweaking, 1 => +remove vertical space characters, 2 => remove underscore. */ + +static const int posix_class_maps[] = { + cbit_word, cbit_digit, -2, /* alpha */ + cbit_lower, -1, 0, /* lower */ + cbit_upper, -1, 0, /* upper */ + cbit_word, -1, 2, /* alnum - word without underscore */ + cbit_print, cbit_cntrl, 0, /* ascii */ + cbit_space, -1, 1, /* blank - a GNU extension */ + cbit_cntrl, -1, 0, /* cntrl */ + cbit_digit, -1, 0, /* digit */ + cbit_graph, -1, 0, /* graph */ + cbit_print, -1, 0, /* print */ + cbit_punct, -1, 0, /* punct */ + cbit_space, -1, 0, /* space */ + cbit_word, -1, 0, /* word - a Perl extension */ + cbit_xdigit,-1, 0 /* xdigit */ +}; + +/* Table of substitutes for \d etc when PCRE_UCP is set. The POSIX class +substitutes must be in the order of the names, defined above, and there are +both positive and negative cases. NULL means no substitute. */ + +#ifdef SUPPORT_UCP +static const pcre_uchar string_PNd[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pNd[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_N, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PXsp[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pXsp[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_s, CHAR_p, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PXwd[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pXwd[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_w, CHAR_d, CHAR_RIGHT_CURLY_BRACKET, '\0' }; + +static const pcre_uchar *substitutes[] = { + string_PNd, /* \D */ + string_pNd, /* \d */ + string_PXsp, /* \S */ /* NOTE: Xsp is Perl space */ + string_pXsp, /* \s */ + string_PXwd, /* \W */ + string_pXwd /* \w */ +}; + +static const pcre_uchar string_pL[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pLl[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pLu[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_pXan[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_h[] = { + CHAR_BACKSLASH, CHAR_h, '\0' }; +static const pcre_uchar string_pXps[] = { + CHAR_BACKSLASH, CHAR_p, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PL[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PLl[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_l, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PLu[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_L, CHAR_u, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_PXan[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_a, CHAR_n, CHAR_RIGHT_CURLY_BRACKET, '\0' }; +static const pcre_uchar string_H[] = { + CHAR_BACKSLASH, CHAR_H, '\0' }; +static const pcre_uchar string_PXps[] = { + CHAR_BACKSLASH, CHAR_P, CHAR_LEFT_CURLY_BRACKET, + CHAR_X, CHAR_p, CHAR_s, CHAR_RIGHT_CURLY_BRACKET, '\0' }; + +static const pcre_uchar *posix_substitutes[] = { + string_pL, /* alpha */ + string_pLl, /* lower */ + string_pLu, /* upper */ + string_pXan, /* alnum */ + NULL, /* ascii */ + string_h, /* blank */ + NULL, /* cntrl */ + string_pNd, /* digit */ + NULL, /* graph */ + NULL, /* print */ + NULL, /* punct */ + string_pXps, /* space */ /* NOTE: Xps is POSIX space */ + string_pXwd, /* word */ + NULL, /* xdigit */ + /* Negated cases */ + string_PL, /* ^alpha */ + string_PLl, /* ^lower */ + string_PLu, /* ^upper */ + string_PXan, /* ^alnum */ + NULL, /* ^ascii */ + string_H, /* ^blank */ + NULL, /* ^cntrl */ + string_PNd, /* ^digit */ + NULL, /* ^graph */ + NULL, /* ^print */ + NULL, /* ^punct */ + string_PXps, /* ^space */ /* NOTE: Xps is POSIX space */ + string_PXwd, /* ^word */ + NULL /* ^xdigit */ +}; +#define POSIX_SUBSIZE (sizeof(posix_substitutes) / sizeof(pcre_uchar *)) +#endif + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +/* The texts of compile-time error messages. These are "char *" because they +are passed to the outside world. Do not ever re-use any error number, because +they are documented. Always add a new error instead. Messages marked DEAD below +are no longer used. This used to be a table of strings, but in order to reduce +the number of relocations needed when a shared library is loaded dynamically, +it is now one long string. We cannot use a table of offsets, because the +lengths of inserts such as XSTRING(MAX_NAME_SIZE) are not known. Instead, we +simply count through to the one we want - this isn't a performance issue +because these strings are used only when there is a compilation error. + +Each substring ends with \0 to insert a null character. This includes the final +substring, so that the whole string ends with \0\0, which can be detected when +counting through. */ + +static const char error_texts[] = + "no error\0" + "\\ at end of pattern\0" + "\\c at end of pattern\0" + "unrecognized character follows \\\0" + "numbers out of order in {} quantifier\0" + /* 5 */ + "number too big in {} quantifier\0" + "missing terminating ] for character class\0" + "invalid escape sequence in character class\0" + "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: unexpected repeat\0" + "unrecognized character after (? or (?-\0" + "POSIX named classes are supported only within a class\0" + "missing )\0" + /* 15 */ + "reference to non-existent subpattern\0" + "erroffset passed as NULL\0" + "unknown option bit(s) set\0" + "missing ) after comment\0" + "parentheses nested too deeply\0" /** DEAD **/ + /* 20 */ + "regular expression is too large\0" + "failed to get memory\0" + "unmatched parentheses\0" + "internal error: code overflow\0" + "unrecognized character after (?<\0" + /* 25 */ + "lookbehind assertion is not fixed length\0" + "malformed number or name after (?(\0" + "conditional group contains more than two branches\0" + "assertion expected after (?(\0" + "(?R or (?[+-]digits must be followed by )\0" + /* 30 */ + "unknown POSIX class name\0" + "POSIX collating elements are not supported\0" + "this version of PCRE is compiled without UTF support\0" + "spare error\0" /** DEAD **/ + "character value in \\x{...} sequence is too large\0" + /* 35 */ + "invalid condition (?(0)\0" + "\\C not allowed in lookbehind assertion\0" + "PCRE does not support \\L, \\l, \\N{name}, \\U, or \\u\0" + "number after (?C is > 255\0" + "closing ) for (?C expected\0" + /* 40 */ + "recursive call could loop indefinitely\0" + "unrecognized character after (?P\0" + "syntax error in subpattern name (missing terminator)\0" + "two named subpatterns have the same name\0" + "invalid UTF-8 string\0" + /* 45 */ + "support for \\P, \\p, and \\X has not been compiled\0" + "malformed \\P or \\p sequence\0" + "unknown property name after \\P or \\p\0" + "subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " characters)\0" + "too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0" + /* 50 */ + "repeated subpattern is too long\0" /** DEAD **/ + "octal value is greater than \\377 in 8-bit non-UTF-8 mode\0" + "internal error: overran compiling workspace\0" + "internal error: previously-checked referenced subpattern not found\0" + "DEFINE group contains more than one branch\0" + /* 55 */ + "repeating a DEFINE group is not allowed\0" /** DEAD **/ + "inconsistent NEWLINE options\0" + "\\g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number\0" + "a numbered reference must not be zero\0" + "an argument is not allowed for (*ACCEPT), (*FAIL), or (*COMMIT)\0" + /* 60 */ + "(*VERB) not recognized\0" + "number is too big\0" + "subpattern name expected\0" + "digit expected after (?+\0" + "] is an invalid data character in JavaScript compatibility mode\0" + /* 65 */ + "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" + "\\c must be followed by an ASCII character\0" + "\\k is not followed by a braced, angle-bracketed, or quoted name\0" + /* 70 */ + "internal error: unknown opcode in find_fixedlength()\0" + "\\N is not supported in a class\0" + "too many forward references\0" + "disallowed Unicode code point (>= 0xd800 && <= 0xdfff)\0" + "invalid UTF-16 string\0" + ; + +/* Table to identify digits and hex digits. This is used when compiling +patterns. Note that the tables in chartables are dependent on the locale, and +may mark arbitrary characters as digits - but the PCRE compiling code expects +to handle only 0-9, a-z, and A-Z as digits when compiling. That is why we have +a private table here. It costs 256 bytes, but it is a lot faster than doing +character value tests (at least in some simple cases I timed), and in some +applications one wants PCRE to compile efficiently as well as match +efficiently. + +For convenience, we use the same bit definitions as in chartables: + + 0x04 decimal digit + 0x08 hexadecimal digit + +Then we can use ctype_digit and ctype_xdigit in the code. */ + +/* Using a simple comparison for decimal numbers rather than a memory read +is much faster, and the resulting code is simpler (the compiler turns it +into a subtraction and unsigned comparison). */ + +#define IS_DIGIT(x) ((x) >= CHAR_0 && (x) <= CHAR_9) + +#ifndef EBCDIC + +/* This is the "normal" case, for ASCII systems, and EBCDIC systems running in +UTF-8 mode. */ + +static const pcre_uint8 digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - ' */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ( - / */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00, /* 8 - ? */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* @ - G */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H - O */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* P - W */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* X - _ */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* ` - g */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h - o */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p - w */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x -127 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */ + +#else + +/* This is the "abnormal" case, for EBCDIC systems not running in UTF-8 mode. */ + +static const pcre_uint8 digitab[] = + { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 10 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32- 39 20 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 30 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 40 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 50 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 88- 95 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 60 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 70 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* 128- g 80 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144- p 90 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160- x A0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 B0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, /* { - G C0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* } - P D0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* \ - X E0 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c, /* 0 - 7 F0 */ + 0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ + +static const pcre_uint8 ebcdic_chartab[] = { /* chartable partial dup */ + 0x80,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 0- 7 */ + 0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 16- 23 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */ + 0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, /* 32- 39 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 40- 47 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 48- 55 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 56- 63 */ + 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - 71 */ + 0x00,0x00,0x00,0x80,0x00,0x80,0x80,0x80, /* 72- | */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* & - 87 */ + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00, /* 88- 95 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - -103 */ + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x80, /* 104- ? */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 112-119 */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 120- " */ + 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* 128- g */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* h -143 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* 144- p */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* q -159 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* 160- x */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* y -175 */ + 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ -183 */ + 0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00, /* 184-191 */ + 0x80,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* { - G */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* H -207 */ + 0x00,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* } - P */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Q -223 */ + 0x00,0x00,0x12,0x12,0x12,0x12,0x12,0x12, /* \ - X */ + 0x12,0x12,0x00,0x00,0x00,0x00,0x00,0x00, /* Y -239 */ + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */ + 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00};/* 8 -255 */ +#endif + + +/* Definition to allow mutual recursion */ + +static BOOL + compile_regex(int, pcre_uchar **, const pcre_uchar **, int *, BOOL, BOOL, int, int, + int *, int *, branch_chain *, compile_data *, int *); + + + +/************************************************* +* Find an error text * +*************************************************/ + +/* The error texts are now all in one long string, to save on relocations. As +some of the text is of unknown length, we can't use a table of offsets. +Instead, just count through the strings. This is not a performance issue +because it happens only when there has been a compilation error. + +Argument: the error number +Returns: pointer to the error string +*/ + +static const char * +find_error_text(int n) +{ +const char *s = error_texts; +for (; n > 0; n--) + { + while (*s++ != 0) {}; + if (*s == 0) return "Error text not found (please report)"; + } +return s; +} + + +/************************************************* +* Expand the workspace * +*************************************************/ + +/* This function is called during the second compiling phase, if the number of +forward references fills the existing workspace, which is originally a block on +the stack. A larger block is obtained from malloc() unless the ultimate limit +has been reached or the increase will be rather small. + +Argument: pointer to the compile data block +Returns: 0 if all went well, else an error number +*/ + +static int +expand_workspace(compile_data *cd) +{ +pcre_uchar *newspace; +int newsize = cd->workspace_size * 2; + +if (newsize > COMPILE_WORK_SIZE_MAX) newsize = COMPILE_WORK_SIZE_MAX; +if (cd->workspace_size >= COMPILE_WORK_SIZE_MAX || + newsize - cd->workspace_size < WORK_SIZE_SAFETY_MARGIN) + return ERR72; + +newspace = (PUBL(malloc))(IN_UCHARS(newsize)); +if (newspace == NULL) return ERR21; +memcpy(newspace, cd->start_workspace, cd->workspace_size * sizeof(pcre_uchar)); +cd->hwm = (pcre_uchar *)newspace + (cd->hwm - cd->start_workspace); +if (cd->workspace_size > COMPILE_WORK_SIZE) + (PUBL(free))((void *)cd->start_workspace); +cd->start_workspace = newspace; +cd->workspace_size = newsize; +return 0; +} + + + +/************************************************* +* Check for counted repeat * +*************************************************/ + +/* This function is called when a '{' is encountered in a place where it might +start a quantifier. It looks ahead to see if it really is a quantifier or not. +It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd} +where the ddds are digits. + +Arguments: + p pointer to the first char after '{' + +Returns: TRUE or FALSE +*/ + +static BOOL +is_counted_repeat(const pcre_uchar *p) +{ +if (!IS_DIGIT(*p)) return FALSE; +p++; +while (IS_DIGIT(*p)) p++; +if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; + +if (*p++ != CHAR_COMMA) return FALSE; +if (*p == CHAR_RIGHT_CURLY_BRACKET) return TRUE; + +if (!IS_DIGIT(*p)) return FALSE; +p++; +while (IS_DIGIT(*p)) p++; + +return (*p == CHAR_RIGHT_CURLY_BRACKET); +} + + + +/************************************************* +* Handle escapes * +*************************************************/ + +/* This function is called when a \ has been encountered. It either returns a +positive value for a simple escape such as \n, or a negative value which +encodes one of the more complicated things such as \d. A backreference to group +n is returned as -(ESC_REF + n); ESC_REF is the highest ESC_xxx macro. When +UTF-8 is enabled, a positive value greater than 255 may be returned. On entry, +ptr is pointing at the \. On exit, it is on the final character of the escape +sequence. + +Arguments: + ptrptr points to the pattern position pointer + errorcodeptr points to the errorcode variable + bracount number of previous extracting brackets + options the options bits + isclass TRUE if inside a character class + +Returns: zero or positive => a data character + negative => a special escape sequence + on error, errorcodeptr is set +*/ + +static int +check_escape(const pcre_uchar **ptrptr, int *errorcodeptr, int bracount, + int options, BOOL isclass) +{ +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +BOOL utf = (options & PCRE_UTF8) != 0; +const pcre_uchar *ptr = *ptrptr + 1; +pcre_int32 c; +int i; + +GETCHARINCTEST(c, ptr); /* Get character value, increment pointer */ +ptr--; /* Set pointer back to the last byte */ + +/* If backslash is at the end of the pattern, it's an error. */ + +if (c == 0) *errorcodeptr = ERR1; + +/* Non-alphanumerics are literals. For digits or letters, do an initial lookup +in a table. A non-zero result is something that can be returned immediately. +Otherwise further processing may be required. */ + +#ifndef EBCDIC /* ASCII/UTF-8 coding */ +/* Not alphanumeric */ +else if (c < CHAR_0 || c > CHAR_z) {} +else if ((i = escapes[c - CHAR_0]) != 0) c = i; + +#else /* EBCDIC coding */ +/* Not alphanumeric */ +else if (c < 'a' || (!MAX_255(c) || (ebcdic_chartab[c] & 0x0E) == 0)) {} +else if ((i = escapes[c - 0x48]) != 0) c = i; +#endif + +/* Escapes that need further processing, or are illegal. */ + +else + { + const pcre_uchar *oldptr; + BOOL braced, negated; + + switch (c) + { + /* A number of Perl escapes are not handled by PCRE. We give an explicit + error. */ + + case CHAR_l: + case CHAR_L: + *errorcodeptr = ERR37; + break; + + case CHAR_u: + if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) + { + /* In JavaScript, \u must be followed by four hexadecimal numbers. + Otherwise it is a lowercase u letter. */ + if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 + && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0 + && MAX_255(ptr[3]) && (digitab[ptr[3]] & ctype_xdigit) != 0 + && MAX_255(ptr[4]) && (digitab[ptr[4]] & ctype_xdigit) != 0) + { + c = 0; + for (i = 0; i < 4; ++i) + { + register int cc = *(++ptr); +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ + c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); +#else /* EBCDIC coding */ + if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ + c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); +#endif + } + } + } + else + *errorcodeptr = ERR37; + break; + + case CHAR_U: + /* In JavaScript, \U is an uppercase U letter. */ + if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) *errorcodeptr = ERR37; + break; + + /* In a character class, \g is just a literal "g". Outside a character + class, \g must be followed by one of a number of specific things: + + (1) A number, either plain or braced. If positive, it is an absolute + backreference. If negative, it is a relative backreference. This is a Perl + 5.10 feature. + + (2) Perl 5.10 also supports \g{name} as a reference to a named group. This + is part of Perl's movement towards a unified syntax for back references. As + this is synonymous with \k{name}, we fudge it up by pretending it really + was \k. + + (3) For Oniguruma compatibility we also support \g followed by a name or a + number either in angle brackets or in single quotes. However, these are + (possibly recursive) subroutine calls, _not_ backreferences. Just return + the -ESC_g code (cf \k). */ + + case CHAR_g: + if (isclass) break; + if (ptr[1] == CHAR_LESS_THAN_SIGN || ptr[1] == CHAR_APOSTROPHE) + { + c = -ESC_g; + break; + } + + /* Handle the Perl-compatible cases */ + + if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) + { + const pcre_uchar *p; + for (p = ptr+2; *p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET; p++) + if (*p != CHAR_MINUS && !IS_DIGIT(*p)) break; + if (*p != 0 && *p != CHAR_RIGHT_CURLY_BRACKET) + { + c = -ESC_k; + break; + } + braced = TRUE; + ptr++; + } + else braced = FALSE; + + if (ptr[1] == CHAR_MINUS) + { + negated = TRUE; + ptr++; + } + else negated = FALSE; + + /* The integer range is limited by the machine's int representation. */ + c = 0; + while (IS_DIGIT(ptr[1])) + { + if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */ + { + c = -1; + break; + } + c = c * 10 + *(++ptr) - CHAR_0; + } + if (((unsigned int)c) > INT_MAX) /* Integer overflow */ + { + while (IS_DIGIT(ptr[1])) + ptr++; + *errorcodeptr = ERR61; + break; + } + + if (braced && *(++ptr) != CHAR_RIGHT_CURLY_BRACKET) + { + *errorcodeptr = ERR57; + break; + } + + if (c == 0) + { + *errorcodeptr = ERR58; + break; + } + + if (negated) + { + if (c > bracount) + { + *errorcodeptr = ERR15; + break; + } + c = bracount - (c - 1); + } + + c = -(ESC_REF + c); + break; + + /* The handling of escape sequences consisting of a string of digits + starting with one that is not zero is not straightforward. By experiment, + the way Perl works seems to be as follows: + + Outside a character class, the digits are read as a decimal number. If the + number is less than 10, or if there are that many previous extracting + left brackets, then it is a back reference. Otherwise, up to three octal + digits are read to form an escaped byte. Thus \123 is likely to be octal + 123 (cf \0123, which is octal 012 followed by the literal 3). If the octal + value is greater than 377, the least significant 8 bits are taken. Inside a + character class, \ followed by a digit is always an octal number. */ + + case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: case CHAR_5: + case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: + + if (!isclass) + { + oldptr = ptr; + /* The integer range is limited by the machine's int representation. */ + c -= CHAR_0; + while (IS_DIGIT(ptr[1])) + { + if (((unsigned int)c) > INT_MAX / 10) /* Integer overflow */ + { + c = -1; + break; + } + c = c * 10 + *(++ptr) - CHAR_0; + } + if (((unsigned int)c) > INT_MAX) /* Integer overflow */ + { + while (IS_DIGIT(ptr[1])) + ptr++; + *errorcodeptr = ERR61; + break; + } + if (c < 10 || c <= bracount) + { + c = -(ESC_REF + c); + break; + } + ptr = oldptr; /* Put the pointer back and fall through */ + } + + /* Handle an octal number following \. If the first digit is 8 or 9, Perl + generates a binary zero byte and treats the digit as a following literal. + Thus we have to pull back the pointer by one. */ + + if ((c = *ptr) >= CHAR_8) + { + ptr--; + c = 0; + break; + } + + /* \0 always starts an octal number, but we may drop through to here with a + larger first octal digit. The original code used just to take the least + significant 8 bits of octal numbers (I think this is what early Perls used + to do). Nowadays we allow for larger numbers in UTF-8 mode and 16-bit mode, + but no more than 3 octal digits. */ + + case CHAR_0: + c -= CHAR_0; + while(i++ < 2 && ptr[1] >= CHAR_0 && ptr[1] <= CHAR_7) + c = c * 8 + *(++ptr) - CHAR_0; +#ifdef COMPILE_PCRE8 + if (!utf && c > 0xff) *errorcodeptr = ERR51; +#endif + break; + + /* \x is complicated. \x{ddd} is a character number which can be greater + than 0xff in utf or non-8bit mode, but only if the ddd are hex digits. + If not, { is treated as a data character. */ + + case CHAR_x: + if ((options & PCRE_JAVASCRIPT_COMPAT) != 0) + { + /* In JavaScript, \x must be followed by two hexadecimal numbers. + Otherwise it is a lowercase x letter. */ + if (MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0 + && MAX_255(ptr[2]) && (digitab[ptr[2]] & ctype_xdigit) != 0) + { + c = 0; + for (i = 0; i < 2; ++i) + { + register int cc = *(++ptr); +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ + c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); +#else /* EBCDIC coding */ + if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ + c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); +#endif + } + } + break; + } + + if (ptr[1] == CHAR_LEFT_CURLY_BRACKET) + { + const pcre_uchar *pt = ptr + 2; + + c = 0; + while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) + { + register int cc = *pt++; + if (c == 0 && cc == CHAR_0) continue; /* Leading zeroes */ + +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ + c = (c << 4) + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); +#else /* EBCDIC coding */ + if (cc >= CHAR_a && cc <= CHAR_z) cc += 64; /* Convert to upper case */ + c = (c << 4) + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); +#endif + +#ifdef COMPILE_PCRE8 + if (c > (utf ? 0x10ffff : 0xff)) { c = -1; break; } +#else +#ifdef COMPILE_PCRE16 + if (c > (utf ? 0x10ffff : 0xffff)) { c = -1; break; } +#endif +#endif + } + + if (c < 0) + { + while (MAX_255(*pt) && (digitab[*pt] & ctype_xdigit) != 0) pt++; + *errorcodeptr = ERR34; + } + + if (*pt == CHAR_RIGHT_CURLY_BRACKET) + { + if (utf && c >= 0xd800 && c <= 0xdfff) *errorcodeptr = ERR73; + ptr = pt; + break; + } + + /* If the sequence of hex digits does not end with '}', then we don't + recognize this construct; fall through to the normal \x handling. */ + } + + /* Read just a single-byte hex-defined char */ + + c = 0; + while (i++ < 2 && MAX_255(ptr[1]) && (digitab[ptr[1]] & ctype_xdigit) != 0) + { + int cc; /* Some compilers don't like */ + cc = *(++ptr); /* ++ in initializers */ +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (cc >= CHAR_a) cc -= 32; /* Convert to upper case */ + c = c * 16 + cc - ((cc < CHAR_A)? CHAR_0 : (CHAR_A - 10)); +#else /* EBCDIC coding */ + if (cc <= CHAR_z) cc += 64; /* Convert to upper case */ + c = c * 16 + cc - ((cc >= CHAR_0)? CHAR_0 : (CHAR_A - 10)); +#endif + } + break; + + /* For \c, a following letter is upper-cased; then the 0x40 bit is flipped. + An error is given if the byte following \c is not an ASCII character. This + coding is ASCII-specific, but then the whole concept of \cx is + ASCII-specific. (However, an EBCDIC equivalent has now been added.) */ + + case CHAR_c: + c = *(++ptr); + if (c == 0) + { + *errorcodeptr = ERR2; + break; + } +#ifndef EBCDIC /* ASCII/UTF-8 coding */ + if (c > 127) /* Excludes all non-ASCII in either mode */ + { + *errorcodeptr = ERR68; + break; + } + if (c >= CHAR_a && c <= CHAR_z) c -= 32; + c ^= 0x40; +#else /* EBCDIC coding */ + if (c >= CHAR_a && c <= CHAR_z) c += 64; + c ^= 0xC0; +#endif + break; + + /* PCRE_EXTRA enables extensions to Perl in the matter of escapes. Any + other alphanumeric following \ is an error if PCRE_EXTRA was set; + otherwise, for Perl compatibility, it is a literal. This code looks a bit + odd, but there used to be some cases other than the default, and there may + be again in future, so I haven't "optimized" it. */ + + default: + if ((options & PCRE_EXTRA) != 0) switch(c) + { + default: + *errorcodeptr = ERR3; + break; + } + break; + } + } + +/* Perl supports \N{name} for character names, as well as plain \N for "not +newline". PCRE does not support \N{name}. However, it does support +quantification such as \N{2,3}. */ + +if (c == -ESC_N && ptr[1] == CHAR_LEFT_CURLY_BRACKET && + !is_counted_repeat(ptr+2)) + *errorcodeptr = ERR37; + +/* If PCRE_UCP is set, we change the values for \d etc. */ + +if ((options & PCRE_UCP) != 0 && c <= -ESC_D && c >= -ESC_w) + c -= (ESC_DU - ESC_D); + +/* Set the pointer to the final character before returning. */ + +*ptrptr = ptr; +return c; +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Handle \P and \p * +*************************************************/ + +/* This function is called after \P or \p has been encountered, provided that +PCRE is compiled with support for Unicode properties. On entry, ptrptr is +pointing at the P or p. On exit, it is pointing at the final character of the +escape sequence. + +Argument: + ptrptr points to the pattern position pointer + negptr points to a boolean that is set TRUE for negation else FALSE + dptr points to an int that is set to the detailed property value + errorcodeptr points to the error code variable + +Returns: type value from ucp_type_table, or -1 for an invalid type +*/ + +static int +get_ucp(const pcre_uchar **ptrptr, BOOL *negptr, int *dptr, int *errorcodeptr) +{ +int c, i, bot, top; +const pcre_uchar *ptr = *ptrptr; +pcre_uchar name[32]; + +c = *(++ptr); +if (c == 0) goto ERROR_RETURN; + +*negptr = FALSE; + +/* \P or \p can be followed by a name in {}, optionally preceded by ^ for +negation. */ + +if (c == CHAR_LEFT_CURLY_BRACKET) + { + if (ptr[1] == CHAR_CIRCUMFLEX_ACCENT) + { + *negptr = TRUE; + ptr++; + } + for (i = 0; i < (int)(sizeof(name) / sizeof(pcre_uchar)) - 1; i++) + { + c = *(++ptr); + if (c == 0) goto ERROR_RETURN; + if (c == CHAR_RIGHT_CURLY_BRACKET) break; + name[i] = c; + } + if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN; + name[i] = 0; + } + +/* Otherwise there is just one following character */ + +else + { + name[0] = c; + name[1] = 0; + } + +*ptrptr = ptr; + +/* Search for a recognized property name using binary chop */ + +bot = 0; +top = PRIV(utt_size); + +while (bot < top) + { + i = (bot + top) >> 1; + c = STRCMP_UC_C8(name, PRIV(utt_names) + PRIV(utt)[i].name_offset); + if (c == 0) + { + *dptr = PRIV(utt)[i].value; + return PRIV(utt)[i].type; + } + if (c > 0) bot = i + 1; else top = i; + } + +*errorcodeptr = ERR47; +*ptrptr = ptr; +return -1; + +ERROR_RETURN: +*errorcodeptr = ERR46; +*ptrptr = ptr; +return -1; +} +#endif + + + + +/************************************************* +* Read repeat counts * +*************************************************/ + +/* Read an item of the form {n,m} and return the values. This is called only +after is_counted_repeat() has confirmed that a repeat-count quantifier exists, +so the syntax is guaranteed to be correct, but we need to check the values. + +Arguments: + p pointer to first char after '{' + minp pointer to int for min + maxp pointer to int for max + returned as -1 if no max + errorcodeptr points to error code variable + +Returns: pointer to '}' on success; + current ptr on error, with errorcodeptr set non-zero +*/ + +static const pcre_uchar * +read_repeat_counts(const pcre_uchar *p, int *minp, int *maxp, int *errorcodeptr) +{ +int min = 0; +int max = -1; + +/* Read the minimum value and do a paranoid check: a negative value indicates +an integer overflow. */ + +while (IS_DIGIT(*p)) min = min * 10 + *p++ - CHAR_0; +if (min < 0 || min > 65535) + { + *errorcodeptr = ERR5; + return p; + } + +/* Read the maximum value if there is one, and again do a paranoid on its size. +Also, max must not be less than min. */ + +if (*p == CHAR_RIGHT_CURLY_BRACKET) max = min; else + { + if (*(++p) != CHAR_RIGHT_CURLY_BRACKET) + { + max = 0; + while(IS_DIGIT(*p)) max = max * 10 + *p++ - CHAR_0; + if (max < 0 || max > 65535) + { + *errorcodeptr = ERR5; + return p; + } + if (max < min) + { + *errorcodeptr = ERR4; + return p; + } + } + } + +/* Fill in the required variables, and pass back the pointer to the terminating +'}'. */ + +*minp = min; +*maxp = max; +return p; +} + + + +/************************************************* +* Subroutine for finding forward reference * +*************************************************/ + +/* This recursive function is called only from find_parens() below. The +top-level call starts at the beginning of the pattern. All other calls must +start at a parenthesis. It scans along a pattern's text looking for capturing +subpatterns, and counting them. If it finds a named pattern that matches the +name it is given, it returns its number. Alternatively, if the name is NULL, it +returns when it reaches a given numbered subpattern. Recursion is used to keep +track of subpatterns that reset the capturing group numbers - the (?| feature. + +This function was originally called only from the second pass, in which we know +that if (?< or (?' or (?P< is encountered, the name will be correctly +terminated because that is checked in the first pass. There is now one call to +this function in the first pass, to check for a recursive back reference by +name (so that we can make the whole group atomic). In this case, we need check +only up to the current position in the pattern, and that is still OK because +and previous occurrences will have been checked. To make this work, the test +for "end of pattern" is a check against cd->end_pattern in the main loop, +instead of looking for a binary zero. This means that the special first-pass +call can adjust cd->end_pattern temporarily. (Checks for binary zero while +processing items within the loop are OK, because afterwards the main loop will +terminate.) + +Arguments: + ptrptr address of the current character pointer (updated) + cd compile background data + name name to seek, or NULL if seeking a numbered subpattern + lorn name length, or subpattern number if name is NULL + xmode TRUE if we are in /x mode + utf TRUE if we are in UTF-8 / UTF-16 mode + count pointer to the current capturing subpattern number (updated) + +Returns: the number of the named subpattern, or -1 if not found +*/ + +static int +find_parens_sub(pcre_uchar **ptrptr, compile_data *cd, const pcre_uchar *name, int lorn, + BOOL xmode, BOOL utf, int *count) +{ +pcre_uchar *ptr = *ptrptr; +int start_count = *count; +int hwm_count = start_count; +BOOL dup_parens = FALSE; + +/* If the first character is a parenthesis, check on the type of group we are +dealing with. The very first call may not start with a parenthesis. */ + +if (ptr[0] == CHAR_LEFT_PARENTHESIS) + { + /* Handle specials such as (*SKIP) or (*UTF8) etc. */ + + if (ptr[1] == CHAR_ASTERISK) ptr += 2; + + /* Handle a normal, unnamed capturing parenthesis. */ + + else if (ptr[1] != CHAR_QUESTION_MARK) + { + *count += 1; + if (name == NULL && *count == lorn) return *count; + ptr++; + } + + /* All cases now have (? at the start. Remember when we are in a group + where the parenthesis numbers are duplicated. */ + + else if (ptr[2] == CHAR_VERTICAL_LINE) + { + ptr += 3; + dup_parens = TRUE; + } + + /* Handle comments; all characters are allowed until a ket is reached. */ + + else if (ptr[2] == CHAR_NUMBER_SIGN) + { + for (ptr += 3; *ptr != 0; ptr++) if (*ptr == CHAR_RIGHT_PARENTHESIS) break; + goto FAIL_EXIT; + } + + /* Handle a condition. If it is an assertion, just carry on so that it + is processed as normal. If not, skip to the closing parenthesis of the + condition (there can't be any nested parens). */ + + else if (ptr[2] == CHAR_LEFT_PARENTHESIS) + { + ptr += 2; + if (ptr[1] != CHAR_QUESTION_MARK) + { + while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; + if (*ptr != 0) ptr++; + } + } + + /* Start with (? but not a condition. */ + + else + { + ptr += 2; + if (*ptr == CHAR_P) ptr++; /* Allow optional P */ + + /* We have to disambiguate (? for named groups */ + + if ((*ptr == CHAR_LESS_THAN_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK && + ptr[1] != CHAR_EQUALS_SIGN) || *ptr == CHAR_APOSTROPHE) + { + int term; + const pcre_uchar *thisname; + *count += 1; + if (name == NULL && *count == lorn) return *count; + term = *ptr++; + if (term == CHAR_LESS_THAN_SIGN) term = CHAR_GREATER_THAN_SIGN; + thisname = ptr; + while (*ptr != term) ptr++; + if (name != NULL && lorn == ptr - thisname && + STRNCMP_UC_UC(name, thisname, lorn) == 0) + return *count; + term++; + } + } + } + +/* Past any initial parenthesis handling, scan for parentheses or vertical +bars. Stop if we get to cd->end_pattern. Note that this is important for the +first-pass call when this value is temporarily adjusted to stop at the current +position. So DO NOT change this to a test for binary zero. */ + +for (; ptr < cd->end_pattern; ptr++) + { + /* Skip over backslashed characters and also entire \Q...\E */ + + if (*ptr == CHAR_BACKSLASH) + { + if (*(++ptr) == 0) goto FAIL_EXIT; + if (*ptr == CHAR_Q) for (;;) + { + while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {}; + if (*ptr == 0) goto FAIL_EXIT; + if (*(++ptr) == CHAR_E) break; + } + continue; + } + + /* Skip over character classes; this logic must be similar to the way they + are handled for real. If the first character is '^', skip it. Also, if the + first few characters (either before or after ^) are \Q\E or \E we skip them + too. This makes for compatibility with Perl. Note the use of STR macros to + encode "Q\\E" so that it works in UTF-8 on EBCDIC platforms. */ + + if (*ptr == CHAR_LEFT_SQUARE_BRACKET) + { + BOOL negate_class = FALSE; + for (;;) + { + if (ptr[1] == CHAR_BACKSLASH) + { + if (ptr[2] == CHAR_E) + ptr+= 2; + else if (STRNCMP_UC_C8(ptr + 2, + STR_Q STR_BACKSLASH STR_E, 3) == 0) + ptr += 4; + else + break; + } + else if (!negate_class && ptr[1] == CHAR_CIRCUMFLEX_ACCENT) + { + negate_class = TRUE; + ptr++; + } + else break; + } + + /* If the next character is ']', it is a data character that must be + skipped, except in JavaScript compatibility mode. */ + + if (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET && + (cd->external_options & PCRE_JAVASCRIPT_COMPAT) == 0) + ptr++; + + while (*(++ptr) != CHAR_RIGHT_SQUARE_BRACKET) + { + if (*ptr == 0) return -1; + if (*ptr == CHAR_BACKSLASH) + { + if (*(++ptr) == 0) goto FAIL_EXIT; + if (*ptr == CHAR_Q) for (;;) + { + while (*(++ptr) != 0 && *ptr != CHAR_BACKSLASH) {}; + if (*ptr == 0) goto FAIL_EXIT; + if (*(++ptr) == CHAR_E) break; + } + continue; + } + } + continue; + } + + /* Skip comments in /x mode */ + + if (xmode && *ptr == CHAR_NUMBER_SIGN) + { + ptr++; + while (*ptr != 0) + { + if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; } + ptr++; +#ifdef SUPPORT_UTF + if (utf) FORWARDCHAR(ptr); +#endif + } + if (*ptr == 0) goto FAIL_EXIT; + continue; + } + + /* Check for the special metacharacters */ + + if (*ptr == CHAR_LEFT_PARENTHESIS) + { + int rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, count); + if (rc > 0) return rc; + if (*ptr == 0) goto FAIL_EXIT; + } + + else if (*ptr == CHAR_RIGHT_PARENTHESIS) + { + if (dup_parens && *count < hwm_count) *count = hwm_count; + goto FAIL_EXIT; + } + + else if (*ptr == CHAR_VERTICAL_LINE && dup_parens) + { + if (*count > hwm_count) hwm_count = *count; + *count = start_count; + } + } + +FAIL_EXIT: +*ptrptr = ptr; +return -1; +} + + + + +/************************************************* +* Find forward referenced subpattern * +*************************************************/ + +/* This function scans along a pattern's text looking for capturing +subpatterns, and counting them. If it finds a named pattern that matches the +name it is given, it returns its number. Alternatively, if the name is NULL, it +returns when it reaches a given numbered subpattern. This is used for forward +references to subpatterns. We used to be able to start this scan from the +current compiling point, using the current count value from cd->bracount, and +do it all in a single loop, but the addition of the possibility of duplicate +subpattern numbers means that we have to scan from the very start, in order to +take account of such duplicates, and to use a recursive function to keep track +of the different types of group. + +Arguments: + cd compile background data + name name to seek, or NULL if seeking a numbered subpattern + lorn name length, or subpattern number if name is NULL + xmode TRUE if we are in /x mode + utf TRUE if we are in UTF-8 / UTF-16 mode + +Returns: the number of the found subpattern, or -1 if not found +*/ + +static int +find_parens(compile_data *cd, const pcre_uchar *name, int lorn, BOOL xmode, + BOOL utf) +{ +pcre_uchar *ptr = (pcre_uchar *)cd->start_pattern; +int count = 0; +int rc; + +/* If the pattern does not start with an opening parenthesis, the first call +to find_parens_sub() will scan right to the end (if necessary). However, if it +does start with a parenthesis, find_parens_sub() will return when it hits the +matching closing parens. That is why we have to have a loop. */ + +for (;;) + { + rc = find_parens_sub(&ptr, cd, name, lorn, xmode, utf, &count); + if (rc > 0 || *ptr++ == 0) break; + } + +return rc; +} + + + + +/************************************************* +* Find first significant op code * +*************************************************/ + +/* This is called by several functions that scan a compiled expression looking +for a fixed first character, or an anchoring op code etc. It skips over things +that do not influence this. For some calls, it makes sense to skip negative +forward and all backward assertions, and also the \b assertion; for others it +does not. + +Arguments: + code pointer to the start of the group + skipassert TRUE if certain assertions are to be skipped + +Returns: pointer to the first significant opcode +*/ + +static const pcre_uchar* +first_significant_code(const pcre_uchar *code, BOOL skipassert) +{ +for (;;) + { + switch ((int)*code) + { + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + if (!skipassert) return code; + do code += GET(code, 1); while (*code == OP_ALT); + code += PRIV(OP_lengths)[*code]; + break; + + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + if (!skipassert) return code; + /* Fall through */ + + case OP_CALLOUT: + case OP_CREF: + case OP_NCREF: + case OP_RREF: + case OP_NRREF: + case OP_DEF: + code += PRIV(OP_lengths)[*code]; + break; + + default: + return code; + } + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Find the fixed length of a branch * +*************************************************/ + +/* Scan a branch and compute the fixed length of subject that will match it, +if the length is fixed. This is needed for dealing with backward assertions. +In UTF8 mode, the result is in characters rather than bytes. The branch is +temporarily terminated with OP_END when this function is called. + +This function is called when a backward assertion is encountered, so that if it +fails, the error message can point to the correct place in the pattern. +However, we cannot do this when the assertion contains subroutine calls, +because they can be forward references. We solve this by remembering this case +and doing the check at the end; a flag specifies which mode we are running in. + +Arguments: + code points to the start of the pattern (the bracket) + utf TRUE in UTF-8 / UTF-16 mode + atend TRUE if called when the pattern is complete + cd the "compile data" structure + +Returns: the fixed length, + or -1 if there is no fixed length, + or -2 if \C was encountered (in UTF-8 mode only) + or -3 if an OP_RECURSE item was encountered and atend is FALSE + or -4 if an unknown opcode was encountered (internal error) +*/ + +static int +find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd) +{ +int length = -1; + +register int branchlength = 0; +register pcre_uchar *cc = code + 1 + LINK_SIZE; + +/* Scan along the opcodes for this branch. If we get to the end of the +branch, check the length against that of the other branches. */ + +for (;;) + { + int d; + pcre_uchar *ce, *cs; + register int op = *cc; + + switch (op) + { + /* We only need to continue for OP_CBRA (normal capturing bracket) and + OP_BRA (normal non-capturing bracket) because the other variants of these + opcodes are all concerned with unlimited repeated groups, which of course + are not of fixed length. */ + + case OP_CBRA: + case OP_BRA: + case OP_ONCE: + case OP_ONCE_NC: + case OP_COND: + d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd); + if (d < 0) return d; + branchlength += d; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* Reached end of a branch; if it's a ket it is the end of a nested call. + If it's ALT it is an alternation in a nested call. An ACCEPT is effectively + an ALT. If it is END it's the end of the outer call. All can be handled by + the same code. Note that we must not include the OP_KETRxxx opcodes here, + because they all imply an unlimited repeat. */ + + case OP_ALT: + case OP_KET: + case OP_END: + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + if (length < 0) length = branchlength; + else if (length != branchlength) return -1; + if (*cc != OP_ALT) return length; + cc += 1 + LINK_SIZE; + branchlength = 0; + break; + + /* A true recursion implies not fixed length, but a subroutine call may + be OK. If the subroutine is a forward reference, we can't deal with + it until the end of the pattern, so return -3. */ + + case OP_RECURSE: + if (!atend) return -3; + cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */ + do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */ + if (cc > cs && cc < ce) return -1; /* Recursion */ + d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd); + if (d < 0) return d; + branchlength += d; + cc += 1 + LINK_SIZE; + break; + + /* Skip over assertive subpatterns */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += PRIV(OP_lengths)[*cc]; + break; + + /* Skip over things that don't match chars */ + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + case OP_THEN_ARG: + cc += cc[1] + PRIV(OP_lengths)[*cc]; + break; + + case OP_CALLOUT: + case OP_CIRC: + case OP_CIRCM: + case OP_CLOSE: + case OP_COMMIT: + case OP_CREF: + case OP_DEF: + case OP_DOLL: + case OP_DOLLM: + case OP_EOD: + case OP_EODN: + case OP_FAIL: + case OP_NCREF: + case OP_NRREF: + case OP_NOT_WORD_BOUNDARY: + case OP_PRUNE: + case OP_REVERSE: + case OP_RREF: + case OP_SET_SOM: + case OP_SKIP: + case OP_SOD: + case OP_SOM: + case OP_THEN: + case OP_WORD_BOUNDARY: + cc += PRIV(OP_lengths)[*cc]; + break; + + /* Handle literal characters */ + + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; + + /* Handle exact repetitions. The count is already in characters, but we + need to skip over a multibyte character in UTF8 mode. */ + + case OP_EXACT: + case OP_EXACTI: + case OP_NOTEXACT: + case OP_NOTEXACTI: + branchlength += GET2(cc,1); + cc += 2 + IMM2_SIZE; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + if (cc[1 + IMM2_SIZE] == OP_PROP || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; + cc += 1 + IMM2_SIZE + 1; + break; + + /* Handle single-char matchers */ + + case OP_PROP: + case OP_NOTPROP: + cc += 2; + /* Fall through */ + + case OP_HSPACE: + case OP_VSPACE: + case OP_NOT_HSPACE: + case OP_NOT_VSPACE: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + branchlength++; + cc++; + break; + + /* The single-byte matcher isn't allowed. This only happens in UTF-8 mode; + otherwise \C is coded as OP_ALLANY. */ + + case OP_ANYBYTE: + return -2; + + /* Check a class for variable quantification */ + +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 + case OP_XCLASS: + cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS]; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += PRIV(OP_lengths)[OP_CLASS]; + + switch (*cc) + { + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + return -1; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(cc,1) != GET2(cc,1+IMM2_SIZE)) return -1; + branchlength += GET2(cc,1); + cc += 1 + 2 * IMM2_SIZE; + break; + + default: + branchlength++; + } + break; + + /* Anything else is variable length */ + + case OP_ANYNL: + case OP_BRAMINZERO: + case OP_BRAPOS: + case OP_BRAPOSZERO: + case OP_BRAZERO: + case OP_CBRAPOS: + case OP_EXTUNI: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_KETRPOS: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_MINQUERY: + case OP_MINQUERYI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_MINUPTO: + case OP_MINUPTOI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: + case OP_NOTPLUS: + case OP_NOTPLUSI: + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: + case OP_NOTQUERY: + case OP_NOTQUERYI: + case OP_NOTSTAR: + case OP_NOTSTARI: + case OP_NOTUPTO: + case OP_NOTUPTOI: + case OP_PLUS: + case OP_PLUSI: + case OP_POSPLUS: + case OP_POSPLUSI: + case OP_POSQUERY: + case OP_POSQUERYI: + case OP_POSSTAR: + case OP_POSSTARI: + case OP_POSUPTO: + case OP_POSUPTOI: + case OP_QUERY: + case OP_QUERYI: + case OP_REF: + case OP_REFI: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCBRA: + case OP_SCBRAPOS: + case OP_SCOND: + case OP_SKIPZERO: + case OP_STAR: + case OP_STARI: + case OP_TYPEMINPLUS: + case OP_TYPEMINQUERY: + case OP_TYPEMINSTAR: + case OP_TYPEMINUPTO: + case OP_TYPEPLUS: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSUPTO: + case OP_TYPEQUERY: + case OP_TYPESTAR: + case OP_TYPEUPTO: + case OP_UPTO: + case OP_UPTOI: + return -1; + + /* Catch unrecognized opcodes so that when new ones are added they + are not forgotten, as has happened in the past. */ + + default: + return -4; + } + } +/* Control never gets here */ +} + + + + +/************************************************* +* Scan compiled regex for specific bracket * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds a +capturing bracket with the given number, or, if the number is negative, an +instance of OP_REVERSE for a lookbehind. The function is global in the C sense +so that it can be called from pcre_study() when finding the minimum matching +length. + +Arguments: + code points to start of expression + utf TRUE in UTF-8 / UTF-16 mode + number the required bracket number or negative to find a lookbehind + +Returns: pointer to the opcode for the bracket, or NULL if not found +*/ + +const pcre_uchar * +PRIV(find_bracket)(const pcre_uchar *code, BOOL utf, int number) +{ +for (;;) + { + register int c = *code; + + if (c == OP_END) return NULL; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + if (c == OP_XCLASS) code += GET(code, 1); + + /* Handle recursion */ + + else if (c == OP_REVERSE) + { + if (number < 0) return (pcre_uchar *)code; + code += PRIV(OP_lengths)[c]; + } + + /* Handle capturing bracket */ + + else if (c == OP_CBRA || c == OP_SCBRA || + c == OP_CBRAPOS || c == OP_SCBRAPOS) + { + int n = GET2(code, 1+LINK_SIZE); + if (n == number) return (pcre_uchar *)code; + code += PRIV(OP_lengths)[c]; + } + + /* Otherwise, we can get the item's length from the table, except that for + repeated character types, we have to test for \p and \P, which have an extra + two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we + must add in its length. */ + + else + { + switch(c) + { + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; + break; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + case OP_TYPEPOSUPTO: + if (code[1 + IMM2_SIZE] == OP_PROP + || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; + break; + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + code += code[1]; + break; + + case OP_THEN_ARG: + code += code[1]; + break; + } + + /* Add in the fixed length from the table */ + + code += PRIV(OP_lengths)[c]; + + /* In UTF-8 mode, opcodes that are followed by a character may be followed by + a multi-byte character. The length in the table is a minimum, so we have to + arrange to skip the extra bytes. */ + +#ifdef SUPPORT_UTF + if (utf) switch(c) + { + case OP_CHAR: + case OP_CHARI: + case OP_EXACT: + case OP_EXACTI: + case OP_UPTO: + case OP_UPTOI: + case OP_MINUPTO: + case OP_MINUPTOI: + case OP_POSUPTO: + case OP_POSUPTOI: + case OP_STAR: + case OP_STARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_POSSTAR: + case OP_POSSTARI: + case OP_PLUS: + case OP_PLUSI: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_POSPLUS: + case OP_POSPLUSI: + case OP_QUERY: + case OP_QUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + case OP_POSQUERY: + case OP_POSQUERYI: + if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); + break; + } +#else + (void)(utf); /* Keep compiler happy by referencing function argument */ +#endif + } + } +} + + + +/************************************************* +* Scan compiled regex for recursion reference * +*************************************************/ + +/* This little function scans through a compiled pattern until it finds an +instance of OP_RECURSE. + +Arguments: + code points to start of expression + utf TRUE in UTF-8 / UTF-16 mode + +Returns: pointer to the opcode for OP_RECURSE, or NULL if not found +*/ + +static const pcre_uchar * +find_recurse(const pcre_uchar *code, BOOL utf) +{ +for (;;) + { + register int c = *code; + if (c == OP_END) return NULL; + if (c == OP_RECURSE) return code; + + /* XCLASS is used for classes that cannot be represented just by a bit + map. This includes negated single high-valued characters. The length in + the table is zero; the actual length is stored in the compiled code. */ + + if (c == OP_XCLASS) code += GET(code, 1); + + /* Otherwise, we can get the item's length from the table, except that for + repeated character types, we have to test for \p and \P, which have an extra + two bytes of parameters, and for MARK/PRUNE/SKIP/THEN with an argument, we + must add in its length. */ + + else + { + switch(c) + { + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; + break; + + case OP_TYPEPOSUPTO: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + if (code[1 + IMM2_SIZE] == OP_PROP + || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; + break; + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + code += code[1]; + break; + + case OP_THEN_ARG: + code += code[1]; + break; + } + + /* Add in the fixed length from the table */ + + code += PRIV(OP_lengths)[c]; + + /* In UTF-8 mode, opcodes that are followed by a character may be followed + by a multi-byte character. The length in the table is a minimum, so we have + to arrange to skip the extra bytes. */ + +#ifdef SUPPORT_UTF + if (utf) switch(c) + { + case OP_CHAR: + case OP_CHARI: + case OP_EXACT: + case OP_EXACTI: + case OP_UPTO: + case OP_UPTOI: + case OP_MINUPTO: + case OP_MINUPTOI: + case OP_POSUPTO: + case OP_POSUPTOI: + case OP_STAR: + case OP_STARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_POSSTAR: + case OP_POSSTARI: + case OP_PLUS: + case OP_PLUSI: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_POSPLUS: + case OP_POSPLUSI: + case OP_QUERY: + case OP_QUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + case OP_POSQUERY: + case OP_POSQUERYI: + if (HAS_EXTRALEN(code[-1])) code += GET_EXTRALEN(code[-1]); + break; + } +#else + (void)(utf); /* Keep compiler happy by referencing function argument */ +#endif + } + } +} + + + +/************************************************* +* Scan compiled branch for non-emptiness * +*************************************************/ + +/* This function scans through a branch of a compiled pattern to see whether it +can match the empty string or not. It is called from could_be_empty() +below and from compile_branch() when checking for an unlimited repeat of a +group that can match nothing. Note that first_significant_code() skips over +backward and negative forward assertions when its final argument is TRUE. If we +hit an unclosed bracket, we return "empty" - this means we've struck an inner +bracket whose current branch will already have been scanned. + +Arguments: + code points to start of search + endcode points to where to stop + utf TRUE if in UTF-8 / UTF-16 mode + cd contains pointers to tables etc. + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode, + BOOL utf, compile_data *cd) +{ +register int c; +for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); + code < endcode; + code = first_significant_code(code + PRIV(OP_lengths)[c], TRUE)) + { + const pcre_uchar *ccode; + + c = *code; + + /* Skip over forward assertions; the other assertions are skipped by + first_significant_code() with a TRUE final argument. */ + + if (c == OP_ASSERT) + { + do code += GET(code, 1); while (*code == OP_ALT); + c = *code; + continue; + } + + /* For a recursion/subroutine call, if its end has been reached, which + implies a backward reference subroutine call, we can scan it. If it's a + forward reference subroutine call, we can't. To detect forward reference + we have to scan up the list that is kept in the workspace. This function is + called only when doing the real compile, not during the pre-compile that + measures the size of the compiled pattern. */ + + if (c == OP_RECURSE) + { + const pcre_uchar *scode; + BOOL empty_branch; + + /* Test for forward reference */ + + for (scode = cd->start_workspace; scode < cd->hwm; scode += LINK_SIZE) + if (GET(scode, 0) == code + 1 - cd->start_code) return TRUE; + + /* Not a forward reference, test for completed backward reference */ + + empty_branch = FALSE; + scode = cd->start_code + GET(code, 1); + if (GET(scode, 1) == 0) return TRUE; /* Unclosed */ + + /* Completed backwards reference */ + + do + { + if (could_be_empty_branch(scode, endcode, utf, cd)) + { + empty_branch = TRUE; + break; + } + scode += GET(scode, 1); + } + while (*scode == OP_ALT); + + if (!empty_branch) return FALSE; /* All branches are non-empty */ + continue; + } + + /* Groups with zero repeats can of course be empty; skip them. */ + + if (c == OP_BRAZERO || c == OP_BRAMINZERO || c == OP_SKIPZERO || + c == OP_BRAPOSZERO) + { + code += PRIV(OP_lengths)[c]; + do code += GET(code, 1); while (*code == OP_ALT); + c = *code; + continue; + } + + /* A nested group that is already marked as "could be empty" can just be + skipped. */ + + if (c == OP_SBRA || c == OP_SBRAPOS || + c == OP_SCBRA || c == OP_SCBRAPOS) + { + do code += GET(code, 1); while (*code == OP_ALT); + c = *code; + continue; + } + + /* For other groups, scan the branches. */ + + if (c == OP_BRA || c == OP_BRAPOS || + c == OP_CBRA || c == OP_CBRAPOS || + c == OP_ONCE || c == OP_ONCE_NC || + c == OP_COND) + { + BOOL empty_branch; + if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ + + /* If a conditional group has only one branch, there is a second, implied, + empty branch, so just skip over the conditional, because it could be empty. + Otherwise, scan the individual branches of the group. */ + + if (c == OP_COND && code[GET(code, 1)] != OP_ALT) + code += GET(code, 1); + else + { + empty_branch = FALSE; + do + { + if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd)) + empty_branch = TRUE; + code += GET(code, 1); + } + while (*code == OP_ALT); + if (!empty_branch) return FALSE; /* All branches are non-empty */ + } + + c = *code; + continue; + } + + /* Handle the other opcodes */ + + switch (c) + { + /* Check for quantifiers after a class. XCLASS is used for classes that + cannot be represented just by a bit map. This includes negated single + high-valued characters. The length in PRIV(OP_lengths)[] is zero; the + actual length is stored in the compiled code, so we must update "code" + here. */ + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: + ccode = code += GET(code, 1); + goto CHECK_CLASS_REPEAT; +#endif + + case OP_CLASS: + case OP_NCLASS: + ccode = code + PRIV(OP_lengths)[OP_CLASS]; + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + CHECK_CLASS_REPEAT: +#endif + + switch (*ccode) + { + case OP_CRSTAR: /* These could be empty; continue */ + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + break; + + default: /* Non-repeat => class must match */ + case OP_CRPLUS: /* These repeats aren't empty */ + case OP_CRMINPLUS: + return FALSE; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(ccode, 1) > 0) return FALSE; /* Minimum > 0 */ + break; + } + break; + + /* Opcodes that must match a character */ + + case OP_PROP: + case OP_NOTPROP: + case OP_EXTUNI: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + case OP_ANYBYTE: + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + case OP_EXACT: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTPOSPLUS: + case OP_NOTEXACT: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSPLUS: + case OP_TYPEEXACT: + return FALSE; + + /* These are going to continue, as they may be empty, but we have to + fudge the length for the \p and \P cases. */ + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPOSSTAR: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSQUERY: + if (code[1] == OP_PROP || code[1] == OP_NOTPROP) code += 2; + break; + + /* Same for these */ + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + if (code[1 + IMM2_SIZE] == OP_PROP + || code[1 + IMM2_SIZE] == OP_NOTPROP) code += 2; + break; + + /* End of branch */ + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_KETRPOS: + case OP_ALT: + return TRUE; + + /* In UTF-8 mode, STAR, MINSTAR, POSSTAR, QUERY, MINQUERY, POSQUERY, UPTO, + MINUPTO, and POSUPTO may be followed by a multibyte character */ + +#ifdef SUPPORT_UTF + case OP_STAR: + case OP_STARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_POSSTAR: + case OP_POSSTARI: + case OP_QUERY: + case OP_QUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + case OP_POSQUERY: + case OP_POSQUERYI: + if (utf && HAS_EXTRALEN(code[1])) code += GET_EXTRALEN(code[1]); + break; + + case OP_UPTO: + case OP_UPTOI: + case OP_MINUPTO: + case OP_MINUPTOI: + case OP_POSUPTO: + case OP_POSUPTOI: + if (utf && HAS_EXTRALEN(code[1 + IMM2_SIZE])) code += GET_EXTRALEN(code[1 + IMM2_SIZE]); + break; +#endif + + /* MARK, and PRUNE/SKIP/THEN with an argument must skip over the argument + string. */ + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + code += code[1]; + break; + + case OP_THEN_ARG: + code += code[1]; + break; + + /* None of the remaining opcodes are required to match a character. */ + + default: + break; + } + } + +return TRUE; +} + + + +/************************************************* +* Scan compiled regex for non-emptiness * +*************************************************/ + +/* This function is called to check for left recursive calls. We want to check +the current branch of the current pattern to see if it could match the empty +string. If it could, we must look outwards for branches at other levels, +stopping when we pass beyond the bracket which is the subject of the recursion. +This function is called only during the real compile, not during the +pre-compile. + +Arguments: + code points to start of the recursion + endcode points to where to stop (current RECURSE item) + bcptr points to the chain of current (unclosed) branch starts + utf TRUE if in UTF-8 / UTF-16 mode + cd pointers to tables etc + +Returns: TRUE if what is matched could be empty +*/ + +static BOOL +could_be_empty(const pcre_uchar *code, const pcre_uchar *endcode, + branch_chain *bcptr, BOOL utf, compile_data *cd) +{ +while (bcptr != NULL && bcptr->current_branch >= code) + { + if (!could_be_empty_branch(bcptr->current_branch, endcode, utf, cd)) + return FALSE; + bcptr = bcptr->outer; + } +return TRUE; +} + + + +/************************************************* +* Check for POSIX class syntax * +*************************************************/ + +/* This function is called when the sequence "[:" or "[." or "[=" is +encountered in a character class. It checks whether this is followed by a +sequence of characters terminated by a matching ":]" or ".]" or "=]". If we +reach an unescaped ']' without the special preceding character, return FALSE. + +Originally, this function only recognized a sequence of letters between the +terminators, but it seems that Perl recognizes any sequence of characters, +though of course unknown POSIX names are subsequently rejected. Perl gives an +"Unknown POSIX class" error for [:f\oo:] for example, where previously PCRE +didn't consider this to be a POSIX class. Likewise for [:1234:]. + +The problem in trying to be exactly like Perl is in the handling of escapes. We +have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX +class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code +below handles the special 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 that not diagnosing bad classes when Perl does, +I think. + +A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. +It seems that the appearance of a nested POSIX class supersedes an apparent +external class. For example, [:a[:digit:]b:] matches "a", "b", ":", or +a digit. + +In Perl, unescaped square brackets may also appear as part of class names. For +example, [:a[:abc]b:] gives unknown POSIX class "[:abc]b:]". However, for +[:a[:abc]b][b:] it gives unknown POSIX class "[:abc]b][b:]", which does not +seem right at all. PCRE does not allow closing square brackets in POSIX class +names. + +Arguments: + ptr pointer to the initial [ + endptr where to return the end pointer + +Returns: TRUE or FALSE +*/ + +static BOOL +check_posix_syntax(const pcre_uchar *ptr, const pcre_uchar **endptr) +{ +int terminator; /* Don't combine these lines; the Solaris cc */ +terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ +for (++ptr; *ptr != 0; ptr++) + { + if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + ptr++; + else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; + else + { + 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; + } + } +return FALSE; +} + + + + +/************************************************* +* Check POSIX class name * +*************************************************/ + +/* This function is called to check the name given in a POSIX-style class entry +such as [:alnum:]. + +Arguments: + ptr points to the first letter + len the length of the name + +Returns: a value representing the name, or -1 if unknown +*/ + +static int +check_posix_name(const pcre_uchar *ptr, int len) +{ +const char *pn = posix_names; +register int yield = 0; +while (posix_name_lengths[yield] != 0) + { + if (len == posix_name_lengths[yield] && + STRNCMP_UC_C8(ptr, pn, len) == 0) return yield; + pn += posix_name_lengths[yield] + 1; + yield++; + } +return -1; +} + + +/************************************************* +* Adjust OP_RECURSE items in repeated group * +*************************************************/ + +/* OP_RECURSE items contain an offset from the start of the regex to the group +that is referenced. This means that groups can be replicated for fixed +repetition simply by copying (because the recursion is allowed to refer to +earlier groups that are outside the current group). However, when a group is +optional (i.e. the minimum quantifier is zero), OP_BRAZERO or OP_SKIPZERO is +inserted before it, after it has been compiled. This means that any OP_RECURSE +items within it that refer to the group itself or any contained groups have to +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). + +Arguments: + group points to the start of the group + adjust the amount by which the group is to be moved + utf TRUE in UTF-8 / UTF-16 mode + cd contains pointers to tables etc. + save_hwm the hwm forward reference pointer at the start of the group + +Returns: nothing +*/ + +static void +adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, + pcre_uchar *save_hwm) +{ +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 = save_hwm; hc < cd->hwm; hc += LINK_SIZE) + { + offset = GET(hc, 0); + if (cd->start_code + offset == ptr + 1) + { + PUT(hc, 0, offset + adjust); + break; + } + } + + /* Otherwise, adjust the recursion offset if it's after the start of this + group. */ + + if (hc >= cd->hwm) + { + offset = GET(ptr, 1); + if (cd->start_code + offset >= group) PUT(ptr, 1, offset + adjust); + } + + ptr += 1 + LINK_SIZE; + } +} + + + +/************************************************* +* Insert an automatic callout point * +*************************************************/ + +/* This function is called when the PCRE_AUTO_CALLOUT option is set, to insert +callout points before each pattern item. + +Arguments: + code current code pointer + ptr current pattern pointer + cd pointers to tables etc + +Returns: new code pointer +*/ + +static pcre_uchar * +auto_callout(pcre_uchar *code, const pcre_uchar *ptr, compile_data *cd) +{ +*code++ = OP_CALLOUT; +*code++ = 255; +PUT(code, 0, (int)(ptr - cd->start_pattern)); /* Pattern offset */ +PUT(code, LINK_SIZE, 0); /* Default length */ +return code + 2 * LINK_SIZE; +} + + + +/************************************************* +* Complete a callout item * +*************************************************/ + +/* A callout item contains the length of the next item in the pattern, which +we can't fill in till after we have reached the relevant point. This is used +for both automatic and manual callouts. + +Arguments: + previous_callout points to previous callout item + ptr current pattern pointer + cd pointers to tables etc + +Returns: nothing +*/ + +static void +complete_callout(pcre_uchar *previous_callout, const pcre_uchar *ptr, compile_data *cd) +{ +int length = (int)(ptr - cd->start_pattern - GET(previous_callout, 2)); +PUT(previous_callout, 2 + LINK_SIZE, length); +} + + + +#ifdef SUPPORT_UCP +/************************************************* +* Get othercase range * +*************************************************/ + +/* This function is passed the start and end of a class range, in UTF-8 mode +with UCP support. It searches up the characters, looking for internal ranges of +characters in the "other" case. Each call returns the next one, updating the +start address. + +Arguments: + cptr points to starting character value; updated + d end value + ocptr where to put start of othercase range + odptr where to put end of othercase range + +Yield: TRUE when range returned; FALSE when no more +*/ + +static BOOL +get_othercase_range(unsigned int *cptr, unsigned int d, unsigned int *ocptr, + unsigned int *odptr) +{ +unsigned int c, othercase, next; + +for (c = *cptr; c <= d; c++) + { if ((othercase = UCD_OTHERCASE(c)) != c) break; } + +if (c > d) return FALSE; + +*ocptr = othercase; +next = othercase + 1; + +for (++c; c <= d; c++) + { + if (UCD_OTHERCASE(c) != next) break; + next++; + } + +*odptr = next - 1; +*cptr = c; + +return TRUE; +} + + + +/************************************************* +* Check a character and a property * +*************************************************/ + +/* This function is called by check_auto_possessive() when a property item +is adjacent to a fixed character. + +Arguments: + c the character + ptype the property type + pdata the data for the type + negated TRUE if it's a negated property (\P or \p{^) + +Returns: TRUE if auto-possessifying is OK +*/ + +static BOOL +check_char_prop(int c, int ptype, int pdata, BOOL negated) +{ +const ucd_record *prop = GET_UCD(c); +switch(ptype) + { + case PT_LAMP: + return (prop->chartype == ucp_Lu || + prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt) == negated; + + case PT_GC: + return (pdata == PRIV(ucp_gentype)[prop->chartype]) == negated; + + case PT_PC: + return (pdata == prop->chartype) == negated; + + case PT_SC: + return (pdata == prop->script) == negated; + + /* These are specials */ + + case PT_ALNUM: + return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N) == negated; + + case PT_SPACE: /* Perl space */ + return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) + == negated; + + case PT_PXSPACE: /* POSIX space */ + return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR) + == negated; + + case PT_WORD: + return (PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE) == negated; + } +return FALSE; +} +#endif /* SUPPORT_UCP */ + + + +/************************************************* +* Check if auto-possessifying is possible * +*************************************************/ + +/* This function is called for unlimited repeats of certain items, to see +whether the next thing could possibly match the repeated item. If not, it makes +sense to automatically possessify the repeated item. + +Arguments: + previous pointer to the repeated opcode + utf TRUE in UTF-8 / UTF-16 mode + ptr next character in pattern + options options bits + cd contains pointers to tables etc. + +Returns: TRUE if possessifying is wanted +*/ + +static BOOL +check_auto_possessive(const pcre_uchar *previous, BOOL utf, + const pcre_uchar *ptr, int options, compile_data *cd) +{ +pcre_int32 c, next; +int op_code = *previous++; + +/* Skip whitespace and comments in extended mode */ + +if ((options & PCRE_EXTENDED) != 0) + { + for (;;) + { + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++; + if (*ptr == CHAR_NUMBER_SIGN) + { + ptr++; + while (*ptr != 0) + { + if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } + ptr++; +#ifdef SUPPORT_UTF + if (utf) FORWARDCHAR(ptr); +#endif + } + } + else break; + } + } + +/* If the next item is one that we can handle, get its value. A non-negative +value is a character, a negative value is an escape value. */ + +if (*ptr == CHAR_BACKSLASH) + { + int temperrorcode = 0; + next = check_escape(&ptr, &temperrorcode, cd->bracount, options, FALSE); + if (temperrorcode != 0) return FALSE; + ptr++; /* Point after the escape sequence */ + } +else if (!MAX_255(*ptr) || (cd->ctypes[*ptr] & ctype_meta) == 0) + { +#ifdef SUPPORT_UTF + if (utf) { GETCHARINC(next, ptr); } else +#endif + next = *ptr++; + } +else return FALSE; + +/* Skip whitespace and comments in extended mode */ + +if ((options & PCRE_EXTENDED) != 0) + { + for (;;) + { + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_space) != 0) ptr++; + if (*ptr == CHAR_NUMBER_SIGN) + { + ptr++; + while (*ptr != 0) + { + if (IS_NEWLINE(ptr)) { ptr += cd->nllen; break; } + ptr++; +#ifdef SUPPORT_UTF + if (utf) FORWARDCHAR(ptr); +#endif + } + } + else break; + } + } + +/* If the next thing is itself optional, we have to give up. */ + +if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK || + STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0) + return FALSE; + +/* Now compare the next item with the previous opcode. First, handle cases when +the next item is a character. */ + +if (next >= 0) switch(op_code) + { + case OP_CHAR: +#ifdef SUPPORT_UTF + GETCHARTEST(c, previous); +#else + c = *previous; +#endif + return c != next; + + /* For CHARI (caseless character) we must check the other case. If we have + Unicode property support, we can use it to test the other case of + high-valued characters. */ + + case OP_CHARI: +#ifdef SUPPORT_UTF + GETCHARTEST(c, previous); +#else + c = *previous; +#endif + if (c == next) return FALSE; +#ifdef SUPPORT_UTF + if (utf) + { + unsigned int othercase; + if (next < 128) othercase = cd->fcc[next]; else +#ifdef SUPPORT_UCP + othercase = UCD_OTHERCASE((unsigned int)next); +#else + othercase = NOTACHAR; +#endif + return (unsigned int)c != othercase; + } + else +#endif /* SUPPORT_UTF */ + return (c != TABLE_GET((unsigned int)next, cd->fcc, next)); /* Non-UTF-8 mode */ + + /* For OP_NOT and OP_NOTI, the data is always a single-byte character. These + opcodes are not used for multi-byte characters, because they are coded using + an XCLASS instead. */ + + case OP_NOT: + return (c = *previous) == next; + + case OP_NOTI: + if ((c = *previous) == next) return TRUE; +#ifdef SUPPORT_UTF + if (utf) + { + unsigned int othercase; + if (next < 128) othercase = cd->fcc[next]; else +#ifdef SUPPORT_UCP + othercase = UCD_OTHERCASE(next); +#else + othercase = NOTACHAR; +#endif + return (unsigned int)c == othercase; + } + else +#endif /* SUPPORT_UTF */ + return (c == (int)(TABLE_GET((unsigned int)next, cd->fcc, next))); /* Non-UTF-8 mode */ + + /* Note that OP_DIGIT etc. are generated only when PCRE_UCP is *not* set. + When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */ + + case OP_DIGIT: + return next > 127 || (cd->ctypes[next] & ctype_digit) == 0; + + case OP_NOT_DIGIT: + return next <= 127 && (cd->ctypes[next] & ctype_digit) != 0; + + case OP_WHITESPACE: + return next > 127 || (cd->ctypes[next] & ctype_space) == 0; + + case OP_NOT_WHITESPACE: + return next <= 127 && (cd->ctypes[next] & ctype_space) != 0; + + case OP_WORDCHAR: + return next > 127 || (cd->ctypes[next] & ctype_word) == 0; + + case OP_NOT_WORDCHAR: + return next <= 127 && (cd->ctypes[next] & ctype_word) != 0; + + case OP_HSPACE: + case OP_NOT_HSPACE: + switch(next) + { + case 0x09: + case 0x20: + case 0xa0: + case 0x1680: + case 0x180e: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x202f: + case 0x205f: + case 0x3000: + return op_code == OP_NOT_HSPACE; + default: + return op_code != OP_NOT_HSPACE; + } + + case OP_ANYNL: + case OP_VSPACE: + case OP_NOT_VSPACE: + switch(next) + { + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x85: + case 0x2028: + case 0x2029: + return op_code == OP_NOT_VSPACE; + default: + return op_code != OP_NOT_VSPACE; + } + +#ifdef SUPPORT_UCP + case OP_PROP: + return check_char_prop(next, previous[0], previous[1], FALSE); + + case OP_NOTPROP: + return check_char_prop(next, previous[0], previous[1], TRUE); +#endif + + default: + return FALSE; + } + + +/* Handle the case when the next item is \d, \s, etc. Note that when PCRE_UCP +is set, \d turns into ESC_du rather than ESC_d, etc., so ESC_d etc. are +generated only when PCRE_UCP is *not* set, that is, when only ASCII +characteristics are recognized. Similarly, the opcodes OP_DIGIT etc. are +replaced by OP_PROP codes when PCRE_UCP is set. */ + +switch(op_code) + { + case OP_CHAR: + case OP_CHARI: +#ifdef SUPPORT_UTF + GETCHARTEST(c, previous); +#else + c = *previous; +#endif + switch(-next) + { + case ESC_d: + return c > 127 || (cd->ctypes[c] & ctype_digit) == 0; + + case ESC_D: + return c <= 127 && (cd->ctypes[c] & ctype_digit) != 0; + + case ESC_s: + return c > 127 || (cd->ctypes[c] & ctype_space) == 0; + + case ESC_S: + return c <= 127 && (cd->ctypes[c] & ctype_space) != 0; + + case ESC_w: + return c > 127 || (cd->ctypes[c] & ctype_word) == 0; + + case ESC_W: + return c <= 127 && (cd->ctypes[c] & ctype_word) != 0; + + case ESC_h: + case ESC_H: + switch(c) + { + case 0x09: + case 0x20: + case 0xa0: + case 0x1680: + case 0x180e: + case 0x2000: + case 0x2001: + case 0x2002: + case 0x2003: + case 0x2004: + case 0x2005: + case 0x2006: + case 0x2007: + case 0x2008: + case 0x2009: + case 0x200A: + case 0x202f: + case 0x205f: + case 0x3000: + return -next != ESC_h; + default: + return -next == ESC_h; + } + + case ESC_v: + case ESC_V: + switch(c) + { + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x85: + case 0x2028: + case 0x2029: + return -next != ESC_v; + default: + return -next == ESC_v; + } + + /* When PCRE_UCP is set, these values get generated for \d etc. Find + their substitutions and process them. The result will always be either + -ESC_p or -ESC_P. Then fall through to process those values. */ + +#ifdef SUPPORT_UCP + case ESC_du: + case ESC_DU: + case ESC_wu: + case ESC_WU: + case ESC_su: + case ESC_SU: + { + int temperrorcode = 0; + ptr = substitutes[-next - ESC_DU]; + next = check_escape(&ptr, &temperrorcode, 0, options, FALSE); + if (temperrorcode != 0) return FALSE; + ptr++; /* For compatibility */ + } + /* Fall through */ + + case ESC_p: + case ESC_P: + { + int ptype, pdata, errorcodeptr; + BOOL negated; + + ptr--; /* Make ptr point at the p or P */ + ptype = get_ucp(&ptr, &negated, &pdata, &errorcodeptr); + if (ptype < 0) return FALSE; + ptr++; /* Point past the final curly ket */ + + /* If the property item is optional, we have to give up. (When generated + from \d etc by PCRE_UCP, this test will have been applied much earlier, + to the original \d etc. At this point, ptr will point to a zero byte. */ + + if (*ptr == CHAR_ASTERISK || *ptr == CHAR_QUESTION_MARK || + STRNCMP_UC_C8(ptr, STR_LEFT_CURLY_BRACKET STR_0 STR_COMMA, 3) == 0) + return FALSE; + + /* Do the property check. */ + + return check_char_prop(c, ptype, pdata, (next == -ESC_P) != negated); + } +#endif + + default: + return FALSE; + } + + /* In principle, support for Unicode properties should be integrated here as + well. It means re-organizing the above code so as to get hold of the property + values before switching on the op-code. However, I wonder how many patterns + combine ASCII \d etc with Unicode properties? (Note that if PCRE_UCP is set, + these op-codes are never generated.) */ + + case OP_DIGIT: + return next == -ESC_D || next == -ESC_s || next == -ESC_W || + next == -ESC_h || next == -ESC_v || next == -ESC_R; + + case OP_NOT_DIGIT: + return next == -ESC_d; + + case OP_WHITESPACE: + return next == -ESC_S || next == -ESC_d || next == -ESC_w || next == -ESC_R; + + case OP_NOT_WHITESPACE: + return next == -ESC_s || next == -ESC_h || next == -ESC_v; + + case OP_HSPACE: + return next == -ESC_S || next == -ESC_H || next == -ESC_d || + next == -ESC_w || next == -ESC_v || next == -ESC_R; + + case OP_NOT_HSPACE: + return next == -ESC_h; + + /* Can't have \S in here because VT matches \S (Perl anomaly) */ + case OP_ANYNL: + case OP_VSPACE: + return next == -ESC_V || next == -ESC_d || next == -ESC_w; + + case OP_NOT_VSPACE: + return next == -ESC_v || next == -ESC_R; + + case OP_WORDCHAR: + return next == -ESC_W || next == -ESC_s || next == -ESC_h || + next == -ESC_v || next == -ESC_R; + + case OP_NOT_WORDCHAR: + return next == -ESC_w || next == -ESC_d; + + default: + return FALSE; + } + +/* Control does not reach here */ +} + + + +/************************************************* +* Compile one branch * +*************************************************/ + +/* Scan the pattern, compiling it into the a vector. If the options are +changed during the branch, the pointer is used to change the external options +bits. This function is used during the pre-compile phase when we are trying +to find out the amount of memory needed, as well as during the real compile +phase. The value of lengthptr distinguishes the two phases. + +Arguments: + optionsptr pointer to the option bits + codeptr points to the pointer to the current code point + ptrptr points to the current pattern pointer + errorcodeptr points to error code variable + firstcharptr set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE) + reqcharptr set to the last literal character required, else < 0 + bcptr points to current branch chain + cond_depth conditional nesting depth + cd contains pointers to tables etc. + lengthptr NULL during the real compile phase + points to length accumulator during pre-compile phase + +Returns: TRUE on success + FALSE, with *errorcodeptr set non-zero on error +*/ + +static BOOL +compile_branch(int *optionsptr, pcre_uchar **codeptr, + const pcre_uchar **ptrptr, int *errorcodeptr, pcre_int32 *firstcharptr, + pcre_int32 *reqcharptr, branch_chain *bcptr, int cond_depth, + compile_data *cd, int *lengthptr) +{ +int repeat_type, op_type; +int repeat_min = 0, repeat_max = 0; /* To please picky compilers */ +int bravalue = 0; +int greedy_default, greedy_non_default; +pcre_int32 firstchar, reqchar; +pcre_int32 zeroreqchar, zerofirstchar; +pcre_int32 req_caseopt, reqvary, tempreqvary; +int options = *optionsptr; /* May change dynamically */ +int after_manual_callout = 0; +int length_prevgroup = 0; +register int c; +register pcre_uchar *code = *codeptr; +pcre_uchar *last_code = code; +pcre_uchar *orig_code = code; +pcre_uchar *tempcode; +BOOL inescq = FALSE; +BOOL groupsetfirstchar = FALSE; +const pcre_uchar *ptr = *ptrptr; +const pcre_uchar *tempptr; +const pcre_uchar *nestptr = NULL; +pcre_uchar *previous = NULL; +pcre_uchar *previous_callout = NULL; +pcre_uchar *save_hwm = NULL; +pcre_uint8 classbits[32]; + +/* We can fish out the UTF-8 setting once and for all into a BOOL, but we +must not do this for other options (e.g. PCRE_EXTENDED) because they may change +dynamically as we process the pattern. */ + +#ifdef SUPPORT_UTF +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +BOOL utf = (options & PCRE_UTF8) != 0; +pcre_uchar utf_chars[6]; +#else +BOOL utf = FALSE; +#endif + +/* Helper variables for OP_XCLASS opcode (for characters > 255). */ + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 +BOOL xclass; +pcre_uchar *class_uchardata; +pcre_uchar *class_uchardata_base; +#endif + +#ifdef PCRE_DEBUG +if (lengthptr != NULL) DPRINTF((">> start branch\n")); +#endif + +/* Set up the default and non-default settings for greediness */ + +greedy_default = ((options & PCRE_UNGREEDY) != 0); +greedy_non_default = greedy_default ^ 1; + +/* Initialize no first byte, no required byte. REQ_UNSET means "no char +matching encountered yet". It gets changed to REQ_NONE if we hit something that +matches a non-fixed char first char; reqchar just remains unset if we never +find one. + +When we hit a repeat whose minimum is zero, we may have to adjust these values +to take the zero repeat into account. This is implemented by setting them to +zerofirstbyte and zeroreqchar when such a repeat is encountered. The individual +item types that can be repeated set these backoff variables appropriately. */ + +firstchar = reqchar = zerofirstchar = zeroreqchar = REQ_UNSET; + +/* The variable req_caseopt contains either the REQ_CASELESS value +or zero, according to the current setting of the caseless flag. The +REQ_CASELESS leaves the lower 28 bit empty. It is added into the +firstchar or reqchar variables to record the case status of the +value. This is used only for ASCII characters. */ + +req_caseopt = ((options & PCRE_CASELESS) != 0)? REQ_CASELESS:0; + +/* Switch on next character until the end of the branch */ + +for (;; ptr++) + { + BOOL negate_class; + BOOL should_flip_negation; + BOOL possessive_quantifier; + BOOL is_quantifier; + BOOL is_recurse; + BOOL reset_bracount; + int class_has_8bitchar; + int class_single_char; + int newoptions; + int recno; + int refsign; + int skipbytes; + int subreqchar; + int subfirstchar; + int terminator; + int mclength; + int tempbracount; + pcre_uchar mcbuffer[8]; + + /* Get next character in the pattern */ + + c = *ptr; + + /* If we are at the end of a nested substitution, revert to the outer level + string. Nesting only happens one level deep. */ + + if (c == 0 && nestptr != NULL) + { + ptr = nestptr; + nestptr = NULL; + c = *ptr; + } + + /* If we are in the pre-compile phase, accumulate the length used for the + previous cycle of this loop. */ + + if (lengthptr != NULL) + { +#ifdef PCRE_DEBUG + if (code > cd->hwm) cd->hwm = code; /* High water info */ +#endif + if (code > cd->start_workspace + cd->workspace_size - + WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */ + { + *errorcodeptr = ERR52; + goto FAILED; + } + + /* There is at least one situation where code goes backwards: this is the + case of a zero quantifier after a class (e.g. [ab]{0}). At compile time, + the class is simply eliminated. However, it is created first, so we have to + allow memory for it. Therefore, don't ever reduce the length at this point. + */ + + if (code < last_code) code = last_code; + + /* Paranoid check for integer overflow */ + + if (OFLOW_MAX - *lengthptr < code - last_code) + { + *errorcodeptr = ERR20; + goto FAILED; + } + + *lengthptr += (int)(code - last_code); + DPRINTF(("length=%d added %d c=%c (0x%x)\n", *lengthptr, + (int)(code - last_code), c, c)); + + /* If "previous" is set and it is not at the start of the work space, move + it back to there, in order to avoid filling up the work space. Otherwise, + if "previous" is NULL, reset the current code pointer to the start. */ + + if (previous != NULL) + { + if (previous > orig_code) + { + memmove(orig_code, previous, IN_UCHARS(code - previous)); + code -= previous - orig_code; + previous = orig_code; + } + } + else code = orig_code; + + /* Remember where this code item starts so we can pick up the length + next time round. */ + + last_code = code; + } + + /* In the real compile phase, just check the workspace used by the forward + reference list. */ + + else if (cd->hwm > cd->start_workspace + cd->workspace_size - + WORK_SIZE_SAFETY_MARGIN) + { + *errorcodeptr = ERR52; + goto FAILED; + } + + /* If in \Q...\E, check for the end; if not, we have a literal */ + + if (inescq && c != 0) + { + if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) + { + inescq = FALSE; + ptr++; + continue; + } + else + { + if (previous_callout != NULL) + { + if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + if ((options & PCRE_AUTO_CALLOUT) != 0) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + goto NORMAL_CHAR; + } + } + + /* Fill in length of a previous callout, except when the next thing is + a quantifier. */ + + is_quantifier = + c == CHAR_ASTERISK || c == CHAR_PLUS || c == CHAR_QUESTION_MARK || + (c == CHAR_LEFT_CURLY_BRACKET && is_counted_repeat(ptr+1)); + + if (!is_quantifier && previous_callout != NULL && + after_manual_callout-- <= 0) + { + if (lengthptr == NULL) /* Don't attempt in pre-compile phase */ + complete_callout(previous_callout, ptr, cd); + previous_callout = NULL; + } + + /* In extended mode, skip white space and comments. */ + + if ((options & PCRE_EXTENDED) != 0) + { + if (MAX_255(*ptr) && (cd->ctypes[c] & ctype_space) != 0) continue; + if (c == CHAR_NUMBER_SIGN) + { + ptr++; + while (*ptr != 0) + { + if (IS_NEWLINE(ptr)) { ptr += cd->nllen - 1; break; } + ptr++; +#ifdef SUPPORT_UTF + if (utf) FORWARDCHAR(ptr); +#endif + } + if (*ptr != 0) continue; + + /* Else fall through to handle end of string */ + c = 0; + } + } + + /* No auto callout for quantifiers. */ + + if ((options & PCRE_AUTO_CALLOUT) != 0 && !is_quantifier) + { + previous_callout = code; + code = auto_callout(code, ptr, cd); + } + + switch(c) + { + /* ===================================================================*/ + case 0: /* The branch terminates at string end */ + case CHAR_VERTICAL_LINE: /* or | or ) */ + case CHAR_RIGHT_PARENTHESIS: + *firstcharptr = firstchar; + *reqcharptr = reqchar; + *codeptr = code; + *ptrptr = ptr; + if (lengthptr != NULL) + { + if (OFLOW_MAX - *lengthptr < code - last_code) + { + *errorcodeptr = ERR20; + goto FAILED; + } + *lengthptr += (int)(code - last_code); /* To include callout length */ + DPRINTF((">> end branch\n")); + } + return TRUE; + + + /* ===================================================================*/ + /* Handle single-character metacharacters. In multiline mode, ^ disables + the setting of any following char as a first character. */ + + case CHAR_CIRCUMFLEX_ACCENT: + previous = NULL; + if ((options & PCRE_MULTILINE) != 0) + { + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + *code++ = OP_CIRCM; + } + else *code++ = OP_CIRC; + break; + + case CHAR_DOLLAR_SIGN: + previous = NULL; + *code++ = ((options & PCRE_MULTILINE) != 0)? OP_DOLLM : OP_DOLL; + break; + + /* There can never be a first char if '.' is first, whatever happens about + repeats. The value of reqchar doesn't change either. */ + + case CHAR_DOT: + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + zerofirstchar = firstchar; + zeroreqchar = reqchar; + previous = code; + *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; + break; + + + /* ===================================================================*/ + /* Character classes. If the included characters are all < 256, we build a + 32-byte bitmap of the permitted characters, except in the special case + where there is only one such character. For negated classes, we build the + map as usual, then invert it at the end. However, we use a different opcode + so that data characters > 255 can be handled correctly. + + If the class contains characters outside the 0-255 range, a different + opcode is compiled. It may optionally have a bit map for characters < 256, + but those above are are explicitly listed afterwards. A flag byte tells + whether the bitmap is present, and whether this is a negated class or not. + + In JavaScript compatibility mode, an isolated ']' causes an error. In + default (Perl) mode, it is treated as a data character. */ + + case CHAR_RIGHT_SQUARE_BRACKET: + if ((cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) + { + *errorcodeptr = ERR64; + goto FAILED; + } + goto NORMAL_CHAR; + + case CHAR_LEFT_SQUARE_BRACKET: + previous = code; + + /* PCRE supports POSIX class stuff inside a class. Perl gives an error if + they are encountered at the top level, so we'll do that too. */ + + if ((ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || + ptr[1] == CHAR_EQUALS_SIGN) && + check_posix_syntax(ptr, &tempptr)) + { + *errorcodeptr = (ptr[1] == CHAR_COLON)? ERR13 : ERR31; + goto FAILED; + } + + /* If the first character is '^', set the negation flag and skip it. Also, + if the first few characters (either before or after ^) are \Q\E or \E we + skip them too. This makes for compatibility with Perl. */ + + negate_class = FALSE; + for (;;) + { + c = *(++ptr); + if (c == CHAR_BACKSLASH) + { + if (ptr[1] == CHAR_E) + ptr++; + else if (STRNCMP_UC_C8(ptr + 1, STR_Q STR_BACKSLASH STR_E, 3) == 0) + ptr += 3; + else + break; + } + else if (!negate_class && c == CHAR_CIRCUMFLEX_ACCENT) + negate_class = TRUE; + else break; + } + + /* Empty classes are allowed in JavaScript compatibility mode. Otherwise, + an initial ']' is taken as a data character -- the code below handles + that. In JS mode, [] must always fail, so generate OP_FAIL, whereas + [^] must match any character, so generate OP_ALLANY. */ + + if (c == CHAR_RIGHT_SQUARE_BRACKET && + (cd->external_options & PCRE_JAVASCRIPT_COMPAT) != 0) + { + *code++ = negate_class? OP_ALLANY : OP_FAIL; + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + zerofirstchar = firstchar; + break; + } + + /* If a class contains a negative special such as \S, we need to flip the + negation flag at the end, so that support for characters > 255 works + correctly (they are all included in the class). */ + + should_flip_negation = FALSE; + + /* For optimization purposes, we track some properties of the class. + class_has_8bitchar will be non-zero, if the class contains at least one + < 256 character. class_single_char will be 1 if the class contains only + a single character. */ + + class_has_8bitchar = 0; + class_single_char = 0; + + /* Initialize the 32-char bit map to all zeros. We build the map in a + temporary bit of memory, in case the class contains only 1 character (less + than 256), because in that case the compiled code doesn't use the bit map. + */ + + memset(classbits, 0, 32 * sizeof(pcre_uint8)); + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + xclass = FALSE; /* No chars >= 256 */ + class_uchardata = code + LINK_SIZE + 2; /* For UTF-8 items */ + class_uchardata_base = class_uchardata; /* For resetting in pass 1 */ +#endif + + /* Process characters until ] is reached. By writing this as a "do" it + means that an initial ] is taken as a data character. At the start of the + loop, c contains the first byte of the character. */ + + if (c != 0) do + { + const pcre_uchar *oldptr; + +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(c)) + { /* Braces are required because the */ + GETCHARLEN(c, ptr, ptr); /* macro generates multiple statements */ + } +#endif + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + /* In the pre-compile phase, accumulate the length of any extra + data and reset the pointer. This is so that very large classes that + contain a zillion > 255 characters no longer overwrite the work space + (which is on the stack). */ + + if (lengthptr != NULL) + { + *lengthptr += class_uchardata - class_uchardata_base; + class_uchardata = class_uchardata_base; + } +#endif + + /* Inside \Q...\E everything is literal except \E */ + + if (inescq) + { + if (c == CHAR_BACKSLASH && ptr[1] == CHAR_E) /* If we are at \E */ + { + inescq = FALSE; /* Reset literal state */ + ptr++; /* Skip the 'E' */ + continue; /* Carry on with next */ + } + goto CHECK_RANGE; /* Could be range if \E follows */ + } + + /* Handle POSIX class names. Perl allows a negation extension of the + form [:^name:]. A square bracket that doesn't match the syntax is + treated as a literal. We also recognize the POSIX constructions + [.ch.] and [=ch=] ("collating elements") and fault them, as Perl + 5.6 and 5.8 do. */ + + if (c == CHAR_LEFT_SQUARE_BRACKET && + (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || + ptr[1] == CHAR_EQUALS_SIGN) && check_posix_syntax(ptr, &tempptr)) + { + BOOL local_negate = FALSE; + int posix_class, taboffset, tabopt; + register const pcre_uint8 *cbits = cd->cbits; + pcre_uint8 pbits[32]; + + if (ptr[1] != CHAR_COLON) + { + *errorcodeptr = ERR31; + goto FAILED; + } + + ptr += 2; + if (*ptr == CHAR_CIRCUMFLEX_ACCENT) + { + local_negate = TRUE; + should_flip_negation = TRUE; /* Note negative special */ + ptr++; + } + + posix_class = check_posix_name(ptr, (int)(tempptr - ptr)); + if (posix_class < 0) + { + *errorcodeptr = ERR30; + goto FAILED; + } + + /* If matching is caseless, upper and lower are converted to + alpha. This relies on the fact that the class table starts with + alpha, lower, upper as the first 3 entries. */ + + if ((options & PCRE_CASELESS) != 0 && posix_class <= 2) + posix_class = 0; + + /* When PCRE_UCP is set, some of the POSIX classes are converted to + different escape sequences that use Unicode properties. */ + +#ifdef SUPPORT_UCP + if ((options & PCRE_UCP) != 0) + { + int pc = posix_class + ((local_negate)? POSIX_SUBSIZE/2 : 0); + if (posix_substitutes[pc] != NULL) + { + nestptr = tempptr + 1; + ptr = posix_substitutes[pc] - 1; + continue; + } + } +#endif + /* In the non-UCP case, we build the bit map for the POSIX class in a + chunk of local store because we may be adding and subtracting from it, + and we don't want to subtract bits that may be in the main map already. + At the end we or the result into the bit map that is being built. */ + + posix_class *= 3; + + /* Copy in the first table (always present) */ + + memcpy(pbits, cbits + posix_class_maps[posix_class], + 32 * sizeof(pcre_uint8)); + + /* If there is a second table, add or remove it as required. */ + + taboffset = posix_class_maps[posix_class + 1]; + tabopt = posix_class_maps[posix_class + 2]; + + if (taboffset >= 0) + { + if (tabopt >= 0) + for (c = 0; c < 32; c++) pbits[c] |= cbits[c + taboffset]; + else + for (c = 0; c < 32; c++) pbits[c] &= ~cbits[c + taboffset]; + } + + /* Not see if we need to remove any special characters. An option + value of 1 removes vertical space and 2 removes underscore. */ + + if (tabopt < 0) tabopt = -tabopt; + if (tabopt == 1) pbits[1] &= ~0x3c; + else if (tabopt == 2) pbits[11] &= 0x7f; + + /* Add the POSIX table or its complement into the main table that is + being built and we are done. */ + + if (local_negate) + for (c = 0; c < 32; c++) classbits[c] |= ~pbits[c]; + else + for (c = 0; c < 32; c++) classbits[c] |= pbits[c]; + + ptr = tempptr + 1; + /* Every class contains at least one < 256 characters. */ + class_has_8bitchar = 1; + /* Every class contains at least two characters. */ + class_single_char = 2; + continue; /* End of POSIX syntax handling */ + } + + /* Backslash may introduce a single character, or it may introduce one + of the specials, which just set a flag. The sequence \b is a special + case. Inside a class (and only there) it is treated as backspace. We + assume that other escapes have more than one character in them, so + speculatively set both class_has_8bitchar and class_single_char bigger + than one. Unrecognized escapes fall through and are either treated + as literal characters (by default), or are faulted if + PCRE_EXTRA is set. */ + + if (c == CHAR_BACKSLASH) + { + c = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE); + if (*errorcodeptr != 0) goto FAILED; + + if (-c == ESC_b) c = CHAR_BS; /* \b is backspace in a class */ + else if (-c == ESC_N) /* \N is not supported in a class */ + { + *errorcodeptr = ERR71; + goto FAILED; + } + else if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) + { + ptr += 2; /* avoid empty string */ + } + else inescq = TRUE; + continue; + } + else if (-c == ESC_E) continue; /* Ignore orphan \E */ + + if (c < 0) + { + register const pcre_uint8 *cbits = cd->cbits; + /* Every class contains at least two < 256 characters. */ + class_has_8bitchar++; + /* Every class contains at least two characters. */ + class_single_char += 2; + + switch (-c) + { +#ifdef SUPPORT_UCP + case ESC_du: /* These are the values given for \d etc */ + case ESC_DU: /* when PCRE_UCP is set. We replace the */ + case ESC_wu: /* escape sequence with an appropriate \p */ + case ESC_WU: /* or \P to test Unicode properties instead */ + case ESC_su: /* of the default ASCII testing. */ + case ESC_SU: + nestptr = ptr; + ptr = substitutes[-c - ESC_DU] - 1; /* Just before substitute */ + class_has_8bitchar--; /* Undo! */ + continue; +#endif + case ESC_d: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_digit]; + continue; + + case ESC_D: + should_flip_negation = TRUE; + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_digit]; + continue; + + case ESC_w: + for (c = 0; c < 32; c++) classbits[c] |= cbits[c+cbit_word]; + continue; + + case ESC_W: + should_flip_negation = TRUE; + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_word]; + continue; + + /* Perl 5.004 onwards omits VT from \s, but we must preserve it + if it was previously set by something earlier in the character + class. */ + + case ESC_s: + classbits[0] |= cbits[cbit_space]; + classbits[1] |= cbits[cbit_space+1] & ~0x08; + for (c = 2; c < 32; c++) classbits[c] |= cbits[c+cbit_space]; + continue; + + case ESC_S: + should_flip_negation = TRUE; + for (c = 0; c < 32; c++) classbits[c] |= ~cbits[c+cbit_space]; + classbits[1] |= 0x08; /* Perl 5.004 onwards omits VT from \s */ + continue; + + case ESC_h: + SETBIT(classbits, 0x09); /* VT */ + SETBIT(classbits, 0x20); /* SPACE */ + SETBIT(classbits, 0xa0); /* NSBP */ +#ifndef COMPILE_PCRE8 + xclass = TRUE; + *class_uchardata++ = XCL_SINGLE; + *class_uchardata++ = 0x1680; + *class_uchardata++ = XCL_SINGLE; + *class_uchardata++ = 0x180e; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x2000; + *class_uchardata++ = 0x200a; + *class_uchardata++ = XCL_SINGLE; + *class_uchardata++ = 0x202f; + *class_uchardata++ = XCL_SINGLE; + *class_uchardata++ = 0x205f; + *class_uchardata++ = XCL_SINGLE; + *class_uchardata++ = 0x3000; +#elif defined SUPPORT_UTF + if (utf) + { + xclass = TRUE; + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(0x1680, class_uchardata); + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(0x180e, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x2000, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x200a, class_uchardata); + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(0x202f, class_uchardata); + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(0x205f, class_uchardata); + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(0x3000, class_uchardata); + } +#endif + continue; + + case ESC_H: + for (c = 0; c < 32; c++) + { + int x = 0xff; + switch (c) + { + case 0x09/8: x ^= 1 << (0x09%8); break; + case 0x20/8: x ^= 1 << (0x20%8); break; + case 0xa0/8: x ^= 1 << (0xa0%8); break; + default: break; + } + classbits[c] |= x; + } +#ifndef COMPILE_PCRE8 + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x0100; + *class_uchardata++ = 0x167f; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x1681; + *class_uchardata++ = 0x180d; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x180f; + *class_uchardata++ = 0x1fff; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x200b; + *class_uchardata++ = 0x202e; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x2030; + *class_uchardata++ = 0x205e; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x2060; + *class_uchardata++ = 0x2fff; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x3001; +#ifdef SUPPORT_UTF + if (utf) + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + else +#endif + *class_uchardata++ = 0xffff; +#elif defined SUPPORT_UTF + if (utf) + { + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x167f, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x1681, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x180d, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x180f, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x1fff, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x200b, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x202e, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x2030, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x205e, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x2060, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x2fff, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x3001, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + } +#endif + continue; + + case ESC_v: + SETBIT(classbits, 0x0a); /* LF */ + SETBIT(classbits, 0x0b); /* VT */ + SETBIT(classbits, 0x0c); /* FF */ + SETBIT(classbits, 0x0d); /* CR */ + SETBIT(classbits, 0x85); /* NEL */ +#ifndef COMPILE_PCRE8 + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x2028; + *class_uchardata++ = 0x2029; +#elif defined SUPPORT_UTF + if (utf) + { + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x2028, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x2029, class_uchardata); + } +#endif + continue; + + case ESC_V: + for (c = 0; c < 32; c++) + { + int x = 0xff; + switch (c) + { + case 0x0a/8: x ^= 1 << (0x0a%8); + x ^= 1 << (0x0b%8); + x ^= 1 << (0x0c%8); + x ^= 1 << (0x0d%8); + break; + case 0x85/8: x ^= 1 << (0x85%8); break; + default: break; + } + classbits[c] |= x; + } + +#ifndef COMPILE_PCRE8 + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x0100; + *class_uchardata++ = 0x2027; + *class_uchardata++ = XCL_RANGE; + *class_uchardata++ = 0x202a; +#ifdef SUPPORT_UTF + if (utf) + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + else +#endif + *class_uchardata++ = 0xffff; +#elif defined SUPPORT_UTF + if (utf) + { + xclass = TRUE; + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x0100, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x2027, class_uchardata); + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x202a, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + } +#endif + continue; + +#ifdef SUPPORT_UCP + case ESC_p: + case ESC_P: + { + BOOL negated; + int pdata; + int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr); + if (ptype < 0) goto FAILED; + xclass = TRUE; + *class_uchardata++ = ((-c == ESC_p) != negated)? + XCL_PROP : XCL_NOTPROP; + *class_uchardata++ = ptype; + *class_uchardata++ = pdata; + class_has_8bitchar--; /* Undo! */ + continue; + } +#endif + /* Unrecognized escapes are faulted if PCRE is running in its + strict mode. By default, for compatibility with Perl, they are + treated as literals. */ + + default: + if ((options & PCRE_EXTRA) != 0) + { + *errorcodeptr = ERR7; + goto FAILED; + } + class_has_8bitchar--; /* Undo the speculative increase. */ + class_single_char -= 2; /* Undo the speculative increase. */ + c = *ptr; /* Get the final character and fall through */ + break; + } + } + + /* Fall through if we have a single character (c >= 0). This may be + greater than 256. */ + + } /* End of backslash handling */ + + /* A single character may be followed by '-' to form a range. However, + Perl does not permit ']' to be the end of the range. A '-' character + at the end is treated as a literal. Perl ignores orphaned \E sequences + entirely. The code for handling \Q and \E is messy. */ + + CHECK_RANGE: + while (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) + { + inescq = FALSE; + ptr += 2; + } + + oldptr = ptr; + + /* Remember \r or \n */ + + if (c == CHAR_CR || c == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; + + /* Check for range */ + + if (!inescq && ptr[1] == CHAR_MINUS) + { + int d; + ptr += 2; + while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) ptr += 2; + + /* If we hit \Q (not followed by \E) at this point, go into escaped + mode. */ + + while (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_Q) + { + ptr += 2; + if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_E) + { ptr += 2; continue; } + inescq = TRUE; + break; + } + + if (*ptr == 0 || (!inescq && *ptr == CHAR_RIGHT_SQUARE_BRACKET)) + { + ptr = oldptr; + goto LONE_SINGLE_CHARACTER; + } + +#ifdef SUPPORT_UTF + if (utf) + { /* Braces are required because the */ + GETCHARLEN(d, ptr, ptr); /* macro generates multiple statements */ + } + else +#endif + d = *ptr; /* Not UTF-8 mode */ + + /* The second part of a range can be a single-character escape, but + not any of the other escapes. Perl 5.6 treats a hyphen as a literal + in such circumstances. */ + + if (!inescq && d == CHAR_BACKSLASH) + { + d = check_escape(&ptr, errorcodeptr, cd->bracount, options, TRUE); + if (*errorcodeptr != 0) goto FAILED; + + /* \b is backspace; any other special means the '-' was literal */ + + if (d < 0) + { + if (d == -ESC_b) d = CHAR_BS; else + { + ptr = oldptr; + goto LONE_SINGLE_CHARACTER; /* A few lines below */ + } + } + } + + /* Check that the two values are in the correct order. Optimize + one-character ranges */ + + if (d < c) + { + *errorcodeptr = ERR8; + goto FAILED; + } + + if (d == c) goto LONE_SINGLE_CHARACTER; /* A few lines below */ + + /* Remember \r or \n */ + + if (d == CHAR_CR || d == CHAR_NL) cd->external_flags |= PCRE_HASCRORLF; + + /* Since we found a character range, single character optimizations + cannot be done anymore. */ + class_single_char = 2; + + /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless + matching, we have to use an XCLASS with extra data items. Caseless + matching for characters > 127 is available only if UCP support is + available. */ + +#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8) + if ((d > 255) || (utf && ((options & PCRE_CASELESS) != 0 && d > 127))) +#elif defined SUPPORT_UTF + if (utf && (d > 255 || ((options & PCRE_CASELESS) != 0 && d > 127))) +#elif !(defined COMPILE_PCRE8) + if (d > 255) +#endif +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + { + xclass = TRUE; + + /* With UCP support, we can find the other case equivalents of + the relevant characters. There may be several ranges. Optimize how + they fit with the basic range. */ + +#ifdef SUPPORT_UCP +#ifndef COMPILE_PCRE8 + if (utf && (options & PCRE_CASELESS) != 0) +#else + if ((options & PCRE_CASELESS) != 0) +#endif + { + unsigned int occ, ocd; + unsigned int cc = c; + unsigned int origd = d; + while (get_othercase_range(&cc, origd, &occ, &ocd)) + { + if (occ >= (unsigned int)c && + ocd <= (unsigned int)d) + continue; /* Skip embedded ranges */ + + if (occ < (unsigned int)c && + ocd >= (unsigned int)c - 1) /* Extend the basic range */ + { /* if there is overlap, */ + c = occ; /* noting that if occ < c */ + continue; /* we can't have ocd > d */ + } /* because a subrange is */ + if (ocd > (unsigned int)d && + occ <= (unsigned int)d + 1) /* always shorter than */ + { /* the basic range. */ + d = ocd; + continue; + } + + if (occ == ocd) + { + *class_uchardata++ = XCL_SINGLE; + } + else + { + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(occ, class_uchardata); + } + class_uchardata += PRIV(ord2utf)(ocd, class_uchardata); + } + } +#endif /* SUPPORT_UCP */ + + /* Now record the original range, possibly modified for UCP caseless + overlapping ranges. */ + + *class_uchardata++ = XCL_RANGE; +#ifdef SUPPORT_UTF +#ifndef COMPILE_PCRE8 + if (utf) + { + class_uchardata += PRIV(ord2utf)(c, class_uchardata); + class_uchardata += PRIV(ord2utf)(d, class_uchardata); + } + else + { + *class_uchardata++ = c; + *class_uchardata++ = d; + } +#else + class_uchardata += PRIV(ord2utf)(c, class_uchardata); + class_uchardata += PRIV(ord2utf)(d, class_uchardata); +#endif +#else /* SUPPORT_UTF */ + *class_uchardata++ = c; + *class_uchardata++ = d; +#endif /* SUPPORT_UTF */ + + /* With UCP support, we are done. Without UCP support, there is no + caseless matching for UTF characters > 127; we can use the bit map + for the smaller ones. As for 16 bit characters without UTF, we + can still use */ + +#ifdef SUPPORT_UCP +#ifndef COMPILE_PCRE8 + if (utf) +#endif + continue; /* With next character in the class */ +#endif /* SUPPORT_UCP */ + +#if defined SUPPORT_UTF && !defined(SUPPORT_UCP) && !(defined COMPILE_PCRE8) + if (utf) + { + if ((options & PCRE_CASELESS) == 0 || c > 127) continue; + /* Adjust upper limit and fall through to set up the map */ + d = 127; + } + else + { + if (c > 255) continue; + /* Adjust upper limit and fall through to set up the map */ + d = 255; + } +#elif defined SUPPORT_UTF && !defined(SUPPORT_UCP) + if ((options & PCRE_CASELESS) == 0 || c > 127) continue; + /* Adjust upper limit and fall through to set up the map */ + d = 127; +#else + if (c > 255) continue; + /* Adjust upper limit and fall through to set up the map */ + d = 255; +#endif /* SUPPORT_UTF && !SUPPORT_UCP && !COMPILE_PCRE8 */ + } +#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ + + /* We use the bit map for 8 bit mode, or when the characters fall + partially or entirely to [0-255] ([0-127] for UCP) ranges. */ + + class_has_8bitchar = 1; + + /* We can save a bit of time by skipping this in the pre-compile. */ + + if (lengthptr == NULL) for (; c <= d; c++) + { + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + int uc = cd->fcc[c]; /* flip case */ + classbits[uc/8] |= (1 << (uc&7)); + } + } + + continue; /* Go get the next char in the class */ + } + + /* Handle a lone single character - we can get here for a normal + non-escape char, or after \ that introduces a single character or for an + apparent range that isn't. */ + + LONE_SINGLE_CHARACTER: + + /* Only the value of 1 matters for class_single_char. */ + if (class_single_char < 2) class_single_char++; + + /* If class_charcount is 1, we saw precisely one character. As long as + there were no negated characters >= 128 and there was no use of \p or \P, + in other words, no use of any XCLASS features, we can optimize. + + In UTF-8 mode, we can optimize the negative case only if there were no + characters >= 128 because OP_NOT and the related opcodes like OP_NOTSTAR + operate on single-bytes characters only. This is an historical hangover. + Maybe one day we can tidy these opcodes to handle multi-byte characters. + + The optimization throws away the bit map. We turn the item into a + 1-character OP_CHAR[I] if it's positive, or OP_NOT[I] if it's negative. + Note that OP_NOT[I] does not support multibyte characters. In the positive + case, it can cause firstchar to be set. Otherwise, there can be no first + char if this item is first, whatever repeat count may follow. In the case + of reqchar, save the previous value for reinstating. */ + +#ifdef SUPPORT_UTF + if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET + && (!utf || !negate_class || c < (MAX_VALUE_FOR_SINGLE_CHAR + 1))) +#else + if (class_single_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) +#endif + { + ptr++; + zeroreqchar = reqchar; + + /* The OP_NOT[I] opcodes work on single characters only. */ + + if (negate_class) + { + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + zerofirstchar = firstchar; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_NOTI: OP_NOT; + *code++ = c; + goto NOT_CHAR; + } + + /* For a single, positive character, get the value into mcbuffer, and + then we can handle this with the normal one-character code. */ + +#ifdef SUPPORT_UTF + if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) + mclength = PRIV(ord2utf)(c, mcbuffer); + else +#endif + { + mcbuffer[0] = c; + mclength = 1; + } + goto ONE_CHAR; + } /* End of 1-char optimization */ + + /* Handle a character that cannot go in the bit map. */ + +#if defined SUPPORT_UTF && !(defined COMPILE_PCRE8) + if ((c > 255) || (utf && ((options & PCRE_CASELESS) != 0 && c > 127))) +#elif defined SUPPORT_UTF + if (utf && (c > 255 || ((options & PCRE_CASELESS) != 0 && c > 127))) +#elif !(defined COMPILE_PCRE8) + if (c > 255) +#endif + +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + { + xclass = TRUE; + *class_uchardata++ = XCL_SINGLE; +#ifdef SUPPORT_UTF +#ifndef COMPILE_PCRE8 + /* In non 8 bit mode, we can get here even if we are not in UTF mode. */ + if (!utf) + *class_uchardata++ = c; + else +#endif + class_uchardata += PRIV(ord2utf)(c, class_uchardata); +#else /* SUPPORT_UTF */ + *class_uchardata++ = c; +#endif /* SUPPORT_UTF */ + +#ifdef SUPPORT_UCP +#ifdef COMPILE_PCRE8 + if ((options & PCRE_CASELESS) != 0) +#else + /* In non 8 bit mode, we can get here even if we are not in UTF mode. */ + if (utf && (options & PCRE_CASELESS) != 0) +#endif + { + unsigned int othercase; + if ((int)(othercase = UCD_OTHERCASE(c)) != c) + { + *class_uchardata++ = XCL_SINGLE; + class_uchardata += PRIV(ord2utf)(othercase, class_uchardata); + } + } +#endif /* SUPPORT_UCP */ + + } + else +#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ + + /* Handle a single-byte character */ + { + class_has_8bitchar = 1; + classbits[c/8] |= (1 << (c&7)); + if ((options & PCRE_CASELESS) != 0) + { + c = cd->fcc[c]; /* flip case */ + classbits[c/8] |= (1 << (c&7)); + } + } + } + + /* Loop until ']' reached. This "while" is the end of the "do" far above. + If we are at the end of an internal nested string, revert to the outer + string. */ + + while (((c = *(++ptr)) != 0 || + (nestptr != NULL && + (ptr = nestptr, nestptr = NULL, c = *(++ptr)) != 0)) && + (c != CHAR_RIGHT_SQUARE_BRACKET || inescq)); + + /* Check for missing terminating ']' */ + + if (c == 0) + { + *errorcodeptr = ERR6; + goto FAILED; + } + + /* If this is the first thing in the branch, there can be no first char + setting, whatever the repeat count. Any reqchar setting must remain + unchanged after any kind of repeat. */ + + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + zerofirstchar = firstchar; + zeroreqchar = reqchar; + + /* If there are characters with values > 255, we have to compile an + extended class, with its own opcode, unless there was a negated special + such as \S in the class, and PCRE_UCP is not set, because in that case all + characters > 255 are in the class, so any that were explicitly given as + well can be ignored. If (when there are explicit characters > 255 that must + be listed) there are no characters < 256, we can omit the bitmap in the + actual compiled code. */ + +#ifdef SUPPORT_UTF + if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0)) +#elif !defined COMPILE_PCRE8 + if (xclass && !should_flip_negation) +#endif +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + { + *class_uchardata++ = XCL_END; /* Marks the end of extra data */ + *code++ = OP_XCLASS; + code += LINK_SIZE; + *code = negate_class? XCL_NOT:0; + + /* If the map is required, move up the extra data to make room for it; + otherwise just move the code pointer to the end of the extra data. */ + + if (class_has_8bitchar > 0) + { + *code++ |= XCL_MAP; + memmove(code + (32 / sizeof(pcre_uchar)), code, + IN_UCHARS(class_uchardata - code)); + memcpy(code, classbits, 32); + code = class_uchardata + (32 / sizeof(pcre_uchar)); + } + else code = class_uchardata; + + /* Now fill in the complete length of the item */ + + PUT(previous, 1, (int)(code - previous)); + break; /* End of class handling */ + } +#endif + + /* If there are no characters > 255, or they are all to be included or + excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the + whole class was negated and whether there were negative specials such as \S + (non-UCP) in the class. Then copy the 32-byte map into the code vector, + negating it if necessary. */ + + *code++ = (negate_class == should_flip_negation) ? OP_CLASS : OP_NCLASS; + if (lengthptr == NULL) /* Save time in the pre-compile phase */ + { + if (negate_class) + for (c = 0; c < 32; c++) classbits[c] = ~classbits[c]; + memcpy(code, classbits, 32); + } + code += 32 / sizeof(pcre_uchar); + NOT_CHAR: + break; + + + /* ===================================================================*/ + /* Various kinds of repeat; '{' is not necessarily a quantifier, but this + has been tested above. */ + + case CHAR_LEFT_CURLY_BRACKET: + if (!is_quantifier) goto NORMAL_CHAR; + ptr = read_repeat_counts(ptr+1, &repeat_min, &repeat_max, errorcodeptr); + if (*errorcodeptr != 0) goto FAILED; + goto REPEAT; + + case CHAR_ASTERISK: + repeat_min = 0; + repeat_max = -1; + goto REPEAT; + + case CHAR_PLUS: + repeat_min = 1; + repeat_max = -1; + goto REPEAT; + + case CHAR_QUESTION_MARK: + repeat_min = 0; + repeat_max = 1; + + REPEAT: + if (previous == NULL) + { + *errorcodeptr = ERR9; + goto FAILED; + } + + if (repeat_min == 0) + { + firstchar = zerofirstchar; /* Adjust for zero repeat */ + reqchar = zeroreqchar; /* Ditto */ + } + + /* Remember whether this is a variable length repeat */ + + reqvary = (repeat_min == repeat_max)? 0 : REQ_VARY; + + op_type = 0; /* Default single-char op codes */ + possessive_quantifier = FALSE; /* Default not possessive quantifier */ + + /* Save start of previous item, in case we have to move it up in order to + insert something before it. */ + + tempcode = previous; + + /* If the next character is '+', we have a possessive quantifier. This + implies greediness, whatever the setting of the PCRE_UNGREEDY option. + If the next character is '?' this is a minimizing repeat, by default, + but if PCRE_UNGREEDY is set, it works the other way round. We change the + repeat type to the non-default. */ + + if (ptr[1] == CHAR_PLUS) + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + ptr++; + } + else if (ptr[1] == CHAR_QUESTION_MARK) + { + repeat_type = greedy_non_default; + ptr++; + } + else repeat_type = greedy_default; + + /* If previous was a recursion call, wrap it in atomic brackets so that + previous becomes the atomic group. All recursions were so wrapped in the + past, but it no longer happens for non-repeated recursions. In fact, the + repeated ones could be re-implemented independently so as not to need this, + but for the moment we rely on the code for repeating groups. */ + + if (*previous == OP_RECURSE) + { + memmove(previous + 1 + LINK_SIZE, previous, IN_UCHARS(1 + LINK_SIZE)); + *previous = OP_ONCE; + PUT(previous, 1, 2 + 2*LINK_SIZE); + previous[2 + 2*LINK_SIZE] = OP_KET; + PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE); + code += 2 + 2 * LINK_SIZE; + length_prevgroup = 3 + 3*LINK_SIZE; + + /* When actually compiling, we need to check whether this was a forward + reference, and if so, adjust the offset. */ + + if (lengthptr == NULL && cd->hwm >= cd->start_workspace + LINK_SIZE) + { + int offset = GET(cd->hwm, -LINK_SIZE); + if (offset == previous + 1 - cd->start_code) + PUT(cd->hwm, -LINK_SIZE, offset + 1 + LINK_SIZE); + } + } + + /* Now handle repetition for the different types of item. */ + + /* If previous was a character match, abolish the item and generate a + repeat item instead. If a char item has a minumum of more than one, ensure + that it is set in reqchar - it might not be if a sequence such as x{3} is + the first thing in a branch because the x will have gone into firstchar + instead. */ + + if (*previous == OP_CHAR || *previous == OP_CHARI) + { + op_type = (*previous == OP_CHAR)? 0 : OP_STARI - OP_STAR; + + /* Deal with UTF characters that take up more than one character. It's + easier to write this out separately than try to macrify it. Use c to + hold the length of the character in bytes, plus UTF_LENGTH to flag that + it's a length rather than a small character. */ + +#ifdef SUPPORT_UTF + if (utf && NOT_FIRSTCHAR(code[-1])) + { + pcre_uchar *lastchar = code - 1; + BACKCHAR(lastchar); + c = (int)(code - lastchar); /* Length of UTF-8 character */ + memcpy(utf_chars, lastchar, IN_UCHARS(c)); /* Save the char */ + c |= UTF_LENGTH; /* Flag c as a length */ + } + else +#endif /* SUPPORT_UTF */ + + /* Handle the case of a single charater - either with no UTF support, or + with UTF disabled, or for a single character UTF character. */ + { + c = code[-1]; + if (repeat_min > 1) reqchar = c | req_caseopt | cd->req_varyopt; + } + + /* If the repetition is unlimited, it pays to see if the next thing on + the line is something that cannot possibly match this character. If so, + automatically possessifying this item gains some performance in the case + where the match fails. */ + + if (!possessive_quantifier && + repeat_max < 0 && + check_auto_possessive(previous, utf, ptr + 1, options, cd)) + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + } + + goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */ + } + + /* If previous was a single negated character ([^a] or similar), we use + one of the special opcodes, replacing it. The code is shared with single- + character repeats by setting opt_type to add a suitable offset into + repeat_type. We can also test for auto-possessification. OP_NOT and OP_NOTI + are currently used only for single-byte chars. */ + + else if (*previous == OP_NOT || *previous == OP_NOTI) + { + op_type = ((*previous == OP_NOT)? OP_NOTSTAR : OP_NOTSTARI) - OP_STAR; + c = previous[1]; + if (!possessive_quantifier && + repeat_max < 0 && + check_auto_possessive(previous, utf, ptr + 1, options, cd)) + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + } + goto OUTPUT_SINGLE_REPEAT; + } + + /* If previous was a character type match (\d or similar), abolish it and + create a suitable repeat item. The code is shared with single-character + repeats by setting op_type to add a suitable offset into repeat_type. Note + the the Unicode property types will be present only when SUPPORT_UCP is + defined, but we don't wrap the little bits of code here because it just + makes it horribly messy. */ + + else if (*previous < OP_EODN) + { + pcre_uchar *oldcode; + int prop_type, prop_value; + op_type = OP_TYPESTAR - OP_STAR; /* Use type opcodes */ + c = *previous; + + if (!possessive_quantifier && + repeat_max < 0 && + check_auto_possessive(previous, utf, ptr + 1, options, cd)) + { + repeat_type = 0; /* Force greedy */ + possessive_quantifier = TRUE; + } + + OUTPUT_SINGLE_REPEAT: + if (*previous == OP_PROP || *previous == OP_NOTPROP) + { + prop_type = previous[1]; + prop_value = previous[2]; + } + else prop_type = prop_value = -1; + + oldcode = code; + code = previous; /* Usually overwrite previous item */ + + /* If the maximum is zero then the minimum must also be zero; Perl allows + this case, so we do too - by simply omitting the item altogether. */ + + if (repeat_max == 0) goto END_REPEAT; + + /*--------------------------------------------------------------------*/ + /* This code is obsolete from release 8.00; the restriction was finally + removed: */ + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */ + /*--------------------------------------------------------------------*/ + + /* Combine the op_type with the repeat_type */ + + repeat_type += op_type; + + /* A minimum of zero is handled either as the special case * or ?, or as + an UPTO, with the maximum given. */ + + if (repeat_min == 0) + { + if (repeat_max == -1) *code++ = OP_STAR + repeat_type; + else if (repeat_max == 1) *code++ = OP_QUERY + repeat_type; + else + { + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + + /* A repeat minimum of 1 is optimized into some special cases. If the + maximum is unlimited, we use OP_PLUS. Otherwise, the original item is + left in place and, if the maximum is greater than 1, we use OP_UPTO with + one less than the maximum. */ + + else if (repeat_min == 1) + { + if (repeat_max == -1) + *code++ = OP_PLUS + repeat_type; + else + { + code = oldcode; /* leave previous item in place */ + if (repeat_max == 1) goto END_REPEAT; + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max - 1); + } + } + + /* The case {n,n} is just an EXACT, while the general case {n,m} is + handled as an EXACT followed by an UPTO. */ + + else + { + *code++ = OP_EXACT + op_type; /* NB EXACT doesn't have repeat_type */ + PUT2INC(code, 0, repeat_min); + + /* If the maximum is unlimited, insert an OP_STAR. Before doing so, + we have to insert the character for the previous code. For a repeated + Unicode property match, there are two extra bytes that define the + required property. In UTF-8 mode, long characters have their length in + c, with the UTF_LENGTH bit as a flag. */ + + if (repeat_max < 0) + { +#ifdef SUPPORT_UTF + if (utf && (c & UTF_LENGTH) != 0) + { + memcpy(code, utf_chars, IN_UCHARS(c & 7)); + code += c & 7; + } + else +#endif + { + *code++ = c; + if (prop_type >= 0) + { + *code++ = prop_type; + *code++ = prop_value; + } + } + *code++ = OP_STAR + repeat_type; + } + + /* Else insert an UPTO if the max is greater than the min, again + preceded by the character, for the previously inserted code. If the + UPTO is just for 1 instance, we can use QUERY instead. */ + + else if (repeat_max != repeat_min) + { +#ifdef SUPPORT_UTF + if (utf && (c & UTF_LENGTH) != 0) + { + memcpy(code, utf_chars, IN_UCHARS(c & 7)); + code += c & 7; + } + else +#endif + *code++ = c; + if (prop_type >= 0) + { + *code++ = prop_type; + *code++ = prop_value; + } + repeat_max -= repeat_min; + + if (repeat_max == 1) + { + *code++ = OP_QUERY + repeat_type; + } + else + { + *code++ = OP_UPTO + repeat_type; + PUT2INC(code, 0, repeat_max); + } + } + } + + /* The character or character type itself comes last in all cases. */ + +#ifdef SUPPORT_UTF + if (utf && (c & UTF_LENGTH) != 0) + { + memcpy(code, utf_chars, IN_UCHARS(c & 7)); + code += c & 7; + } + else +#endif + *code++ = c; + + /* For a repeated Unicode property match, there are two extra bytes that + define the required property. */ + +#ifdef SUPPORT_UCP + if (prop_type >= 0) + { + *code++ = prop_type; + *code++ = prop_value; + } +#endif + } + + /* If previous was a character class or a back reference, we put the repeat + stuff after it, but just skip the item if the repeat was {0,0}. */ + + else if (*previous == OP_CLASS || + *previous == OP_NCLASS || +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + *previous == OP_XCLASS || +#endif + *previous == OP_REF || + *previous == OP_REFI) + { + if (repeat_max == 0) + { + code = previous; + goto END_REPEAT; + } + + /*--------------------------------------------------------------------*/ + /* This code is obsolete from release 8.00; the restriction was finally + removed: */ + + /* All real repeats make it impossible to handle partial matching (maybe + one day we will be able to remove this restriction). */ + + /* if (repeat_max != 1) cd->external_flags |= PCRE_NOPARTIAL; */ + /*--------------------------------------------------------------------*/ + + if (repeat_min == 0 && repeat_max == -1) + *code++ = OP_CRSTAR + repeat_type; + else if (repeat_min == 1 && repeat_max == -1) + *code++ = OP_CRPLUS + repeat_type; + else if (repeat_min == 0 && repeat_max == 1) + *code++ = OP_CRQUERY + repeat_type; + else + { + *code++ = OP_CRRANGE + repeat_type; + PUT2INC(code, 0, repeat_min); + if (repeat_max == -1) repeat_max = 0; /* 2-byte encoding for max */ + PUT2INC(code, 0, repeat_max); + } + } + + /* If previous was a bracket group, we may have to replicate it in certain + cases. Note that at this point we can encounter only the "basic" bracket + opcodes such as BRA and CBRA, as this is the place where they get converted + into the more special varieties such as BRAPOS and SBRA. A test for >= + OP_ASSERT and <= OP_COND includes ASSERT, ASSERT_NOT, ASSERTBACK, + ASSERTBACK_NOT, ONCE, BRA, CBRA, and COND. Originally, PCRE did not allow + repetition of assertions, but now it does, for Perl compatibility. */ + + else if (*previous >= OP_ASSERT && *previous <= OP_COND) + { + register int i; + int len = (int)(code - previous); + pcre_uchar *bralink = NULL; + pcre_uchar *brazeroptr = NULL; + + /* Repeating a DEFINE group is pointless, but Perl allows the syntax, so + we just ignore the repeat. */ + + if (*previous == OP_COND && previous[LINK_SIZE+1] == OP_DEF) + goto END_REPEAT; + + /* There is no sense in actually repeating assertions. The only potential + use of repetition is in cases when the assertion is optional. Therefore, + if the minimum is greater than zero, just ignore the repeat. If the + maximum is not not zero or one, set it to 1. */ + + if (*previous < OP_ONCE) /* Assertion */ + { + if (repeat_min > 0) goto END_REPEAT; + if (repeat_max < 0 || repeat_max > 1) repeat_max = 1; + } + + /* The case of a zero minimum is special because of the need to stick + OP_BRAZERO in front of it, and because the group appears once in the + data, whereas in other cases it appears the minimum number of times. For + this reason, it is simplest to treat this case separately, as otherwise + the code gets far too messy. There are several special subcases when the + minimum is zero. */ + + if (repeat_min == 0) + { + /* If the maximum is also zero, we used to just omit the group from the + output altogether, like this: + + ** if (repeat_max == 0) + ** { + ** code = previous; + ** goto END_REPEAT; + ** } + + However, that fails when a group or a subgroup within it is referenced + as a subroutine from elsewhere in the pattern, so now we stick in + OP_SKIPZERO in front of it so that it is skipped on execution. As we + don't have a list of which groups are referenced, we cannot do this + selectively. + + If the maximum is 1 or unlimited, we just have to stick in the BRAZERO + and do no more at this point. However, we do need to adjust any + OP_RECURSE calls inside the group that refer to the group itself or any + internal or forward referenced group, because the offset is from the + start of the whole regex. Temporarily terminate the pattern while doing + this. */ + + if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ + { + *code = OP_END; + adjust_recurse(previous, 1, utf, cd, save_hwm); + memmove(previous + 1, previous, IN_UCHARS(len)); + code++; + if (repeat_max == 0) + { + *previous++ = OP_SKIPZERO; + goto END_REPEAT; + } + brazeroptr = previous; /* Save for possessive optimizing */ + *previous++ = OP_BRAZERO + repeat_type; + } + + /* If the maximum is greater than 1 and limited, we have to replicate + in a nested fashion, sticking OP_BRAZERO before each set of brackets. + The first one has to be handled carefully because it's the original + copy, which has to be moved up. The remainder can be handled by code + that is common with the non-zero minimum case below. We have to + adjust the value or repeat_max, since one less copy is required. Once + again, we may have to adjust any OP_RECURSE calls inside the group. */ + + else + { + int offset; + *code = OP_END; + adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm); + memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); + code += 2 + LINK_SIZE; + *previous++ = OP_BRAZERO + repeat_type; + *previous++ = OP_BRA; + + /* We chain together the bracket offset fields that have to be + filled in later when the ends of the brackets are reached. */ + + offset = (bralink == NULL)? 0 : (int)(previous - bralink); + bralink = previous; + PUTINC(previous, 0, offset); + } + + repeat_max--; + } + + /* If the minimum is greater than zero, replicate the group as many + times as necessary, and adjust the maximum to the number of subsequent + copies that we need. If we set a first char from the group, and didn't + set a required char, copy the latter from the former. If there are any + forward reference subroutine calls in the group, there will be entries on + the workspace list; replicate these with an appropriate increment. */ + + else + { + if (repeat_min > 1) + { + /* In the pre-compile phase, we don't actually do the replication. We + just adjust the length as if we had. Do some paranoid checks for + potential integer overflow. The INT64_OR_DOUBLE type is a 64-bit + integer type when available, otherwise double. */ + + if (lengthptr != NULL) + { + int delta = (repeat_min - 1)*length_prevgroup; + if ((INT64_OR_DOUBLE)(repeat_min - 1)* + (INT64_OR_DOUBLE)length_prevgroup > + (INT64_OR_DOUBLE)INT_MAX || + OFLOW_MAX - *lengthptr < delta) + { + *errorcodeptr = ERR20; + goto FAILED; + } + *lengthptr += delta; + } + + /* This is compiling for real. If there is a set first byte for + the group, and we have not yet set a "required byte", set it. Make + sure there is enough workspace for copying forward references before + doing the copy. */ + + else + { + if (groupsetfirstchar && reqchar < 0) reqchar = firstchar; + + for (i = 1; i < repeat_min; i++) + { + pcre_uchar *hc; + pcre_uchar *this_hwm = cd->hwm; + memcpy(code, previous, IN_UCHARS(len)); + + while (cd->hwm > cd->start_workspace + cd->workspace_size - + WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) + { + int save_offset = save_hwm - cd->start_workspace; + int this_offset = this_hwm - cd->start_workspace; + *errorcodeptr = expand_workspace(cd); + if (*errorcodeptr != 0) goto FAILED; + save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; + this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; + } + + for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) + { + PUT(cd->hwm, 0, GET(hc, 0) + len); + cd->hwm += LINK_SIZE; + } + save_hwm = this_hwm; + code += len; + } + } + } + + if (repeat_max > 0) repeat_max -= repeat_min; + } + + /* This code is common to both the zero and non-zero minimum cases. If + the maximum is limited, it replicates the group in a nested fashion, + remembering the bracket starts on a stack. In the case of a zero minimum, + the first one was set up above. In all cases the repeat_max now specifies + the number of additional copies needed. Again, we must remember to + replicate entries on the forward reference list. */ + + if (repeat_max >= 0) + { + /* In the pre-compile phase, we don't actually do the replication. We + just adjust the length as if we had. For each repetition we must add 1 + to the length for BRAZERO and for all but the last repetition we must + add 2 + 2*LINKSIZE to allow for the nesting that occurs. Do some + paranoid checks to avoid integer overflow. The INT64_OR_DOUBLE type is + a 64-bit integer type when available, otherwise double. */ + + if (lengthptr != NULL && repeat_max > 0) + { + int delta = repeat_max * (length_prevgroup + 1 + 2 + 2*LINK_SIZE) - + 2 - 2*LINK_SIZE; /* Last one doesn't nest */ + if ((INT64_OR_DOUBLE)repeat_max * + (INT64_OR_DOUBLE)(length_prevgroup + 1 + 2 + 2*LINK_SIZE) + > (INT64_OR_DOUBLE)INT_MAX || + OFLOW_MAX - *lengthptr < delta) + { + *errorcodeptr = ERR20; + goto FAILED; + } + *lengthptr += delta; + } + + /* This is compiling for real */ + + else for (i = repeat_max - 1; i >= 0; i--) + { + pcre_uchar *hc; + pcre_uchar *this_hwm = cd->hwm; + + *code++ = OP_BRAZERO + repeat_type; + + /* All but the final copy start a new nesting, maintaining the + chain of brackets outstanding. */ + + if (i != 0) + { + int offset; + *code++ = OP_BRA; + offset = (bralink == NULL)? 0 : (int)(code - bralink); + bralink = code; + PUTINC(code, 0, offset); + } + + memcpy(code, previous, IN_UCHARS(len)); + + /* Ensure there is enough workspace for forward references before + copying them. */ + + while (cd->hwm > cd->start_workspace + cd->workspace_size - + WORK_SIZE_SAFETY_MARGIN - (this_hwm - save_hwm)) + { + int save_offset = save_hwm - cd->start_workspace; + int this_offset = this_hwm - cd->start_workspace; + *errorcodeptr = expand_workspace(cd); + if (*errorcodeptr != 0) goto FAILED; + save_hwm = (pcre_uchar *)cd->start_workspace + save_offset; + this_hwm = (pcre_uchar *)cd->start_workspace + this_offset; + } + + for (hc = save_hwm; hc < this_hwm; hc += LINK_SIZE) + { + PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1)); + cd->hwm += LINK_SIZE; + } + save_hwm = this_hwm; + code += len; + } + + /* Now chain through the pending brackets, and fill in their length + fields (which are holding the chain links pro tem). */ + + while (bralink != NULL) + { + int oldlinkoffset; + int offset = (int)(code - bralink + 1); + pcre_uchar *bra = code - offset; + oldlinkoffset = GET(bra, 1); + bralink = (oldlinkoffset == 0)? NULL : bralink - oldlinkoffset; + *code++ = OP_KET; + PUTINC(code, 0, offset); + PUT(bra, 1, offset); + } + } + + /* If the maximum is unlimited, set a repeater in the final copy. For + ONCE brackets, that's all we need to do. However, possessively repeated + ONCE brackets can be converted into non-capturing brackets, as the + behaviour of (?:xx)++ is the same as (?>xx)++ and this saves having to + deal with possessive ONCEs specially. + + Otherwise, when we are doing the actual compile phase, check to see + whether this group is one that could match an empty string. If so, + convert the initial operator to the S form (e.g. OP_BRA -> OP_SBRA) so + that runtime checking can be done. [This check is also applied to ONCE + groups at runtime, but in a different way.] + + Then, if the quantifier was possessive and the bracket is not a + conditional, we convert the BRA code to the POS form, and the KET code to + KETRPOS. (It turns out to be convenient at runtime to detect this kind of + subpattern at both the start and at the end.) The use of special opcodes + makes it possible to reduce greatly the stack usage in pcre_exec(). If + the group is preceded by OP_BRAZERO, convert this to OP_BRAPOSZERO. + + Then, if the minimum number of matches is 1 or 0, cancel the possessive + flag so that the default action below, of wrapping everything inside + atomic brackets, does not happen. When the minimum is greater than 1, + there will be earlier copies of the group, and so we still have to wrap + the whole thing. */ + + else + { + pcre_uchar *ketcode = code - 1 - LINK_SIZE; + pcre_uchar *bracode = ketcode - GET(ketcode, 1); + + /* Convert possessive ONCE brackets to non-capturing */ + + if ((*bracode == OP_ONCE || *bracode == OP_ONCE_NC) && + possessive_quantifier) *bracode = OP_BRA; + + /* For non-possessive ONCE brackets, all we need to do is to + set the KET. */ + + if (*bracode == OP_ONCE || *bracode == OP_ONCE_NC) + *ketcode = OP_KETRMAX + repeat_type; + + /* Handle non-ONCE brackets and possessive ONCEs (which have been + converted to non-capturing above). */ + + else + { + /* In the compile phase, check for empty string matching. */ + + if (lengthptr == NULL) + { + pcre_uchar *scode = bracode; + do + { + if (could_be_empty_branch(scode, ketcode, utf, cd)) + { + *bracode += OP_SBRA - OP_BRA; + break; + } + scode += GET(scode, 1); + } + while (*scode == OP_ALT); + } + + /* Handle possessive quantifiers. */ + + if (possessive_quantifier) + { + /* For COND brackets, we wrap the whole thing in a possessively + repeated non-capturing bracket, because we have not invented POS + versions of the COND opcodes. Because we are moving code along, we + must ensure that any pending recursive references are updated. */ + + if (*bracode == OP_COND || *bracode == OP_SCOND) + { + int nlen = (int)(code - bracode); + *code = OP_END; + adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm); + memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); + code += 1 + LINK_SIZE; + nlen += 1 + LINK_SIZE; + *bracode = OP_BRAPOS; + *code++ = OP_KETRPOS; + PUTINC(code, 0, nlen); + PUT(bracode, 1, nlen); + } + + /* For non-COND brackets, we modify the BRA code and use KETRPOS. */ + + else + { + *bracode += 1; /* Switch to xxxPOS opcodes */ + *ketcode = OP_KETRPOS; + } + + /* If the minimum is zero, mark it as possessive, then unset the + possessive flag when the minimum is 0 or 1. */ + + if (brazeroptr != NULL) *brazeroptr = OP_BRAPOSZERO; + if (repeat_min < 2) possessive_quantifier = FALSE; + } + + /* Non-possessive quantifier */ + + else *ketcode = OP_KETRMAX + repeat_type; + } + } + } + + /* If previous is OP_FAIL, it was generated by an empty class [] in + JavaScript mode. The other ways in which OP_FAIL can be generated, that is + by (*FAIL) or (?!) set previous to NULL, which gives a "nothing to repeat" + error above. We can just ignore the repeat in JS case. */ + + else if (*previous == OP_FAIL) goto END_REPEAT; + + /* Else there's some kind of shambles */ + + else + { + *errorcodeptr = ERR11; + goto FAILED; + } + + /* If the character following a repeat is '+', or if certain optimization + tests above succeeded, possessive_quantifier is TRUE. For some opcodes, + there are special alternative opcodes for this case. For anything else, we + wrap the entire repeated item inside OP_ONCE brackets. Logically, the '+' + notation is just syntactic sugar, taken from Sun's Java package, but the + special opcodes can optimize it. + + Some (but not all) possessively repeated subpatterns have already been + completely handled in the code just above. For them, possessive_quantifier + is always FALSE at this stage. + + Note that the repeated item starts at tempcode, not at previous, which + might be the first part of a string whose (former) last char we repeated. + + Possessifying an 'exact' quantifier has no effect, so we can ignore it. But + an 'upto' may follow. We skip over an 'exact' item, and then test the + length of what remains before proceeding. */ + + if (possessive_quantifier) + { + int len; + + if (*tempcode == OP_TYPEEXACT) + tempcode += PRIV(OP_lengths)[*tempcode] + + ((tempcode[1 + IMM2_SIZE] == OP_PROP + || tempcode[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); + + else if (*tempcode == OP_EXACT || *tempcode == OP_NOTEXACT) + { + tempcode += PRIV(OP_lengths)[*tempcode]; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(tempcode[-1])) + tempcode += GET_EXTRALEN(tempcode[-1]); +#endif + } + + len = (int)(code - tempcode); + if (len > 0) switch (*tempcode) + { + case OP_STAR: *tempcode = OP_POSSTAR; break; + case OP_PLUS: *tempcode = OP_POSPLUS; break; + case OP_QUERY: *tempcode = OP_POSQUERY; break; + case OP_UPTO: *tempcode = OP_POSUPTO; break; + + case OP_STARI: *tempcode = OP_POSSTARI; break; + case OP_PLUSI: *tempcode = OP_POSPLUSI; break; + case OP_QUERYI: *tempcode = OP_POSQUERYI; break; + case OP_UPTOI: *tempcode = OP_POSUPTOI; break; + + case OP_NOTSTAR: *tempcode = OP_NOTPOSSTAR; break; + case OP_NOTPLUS: *tempcode = OP_NOTPOSPLUS; break; + case OP_NOTQUERY: *tempcode = OP_NOTPOSQUERY; break; + case OP_NOTUPTO: *tempcode = OP_NOTPOSUPTO; break; + + case OP_NOTSTARI: *tempcode = OP_NOTPOSSTARI; break; + case OP_NOTPLUSI: *tempcode = OP_NOTPOSPLUSI; break; + case OP_NOTQUERYI: *tempcode = OP_NOTPOSQUERYI; break; + case OP_NOTUPTOI: *tempcode = OP_NOTPOSUPTOI; break; + + case OP_TYPESTAR: *tempcode = OP_TYPEPOSSTAR; break; + case OP_TYPEPLUS: *tempcode = OP_TYPEPOSPLUS; break; + case OP_TYPEQUERY: *tempcode = OP_TYPEPOSQUERY; break; + case OP_TYPEUPTO: *tempcode = OP_TYPEPOSUPTO; break; + + /* Because we are moving code along, we must ensure that any + pending recursive references are updated. */ + + default: + *code = OP_END; + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm); + memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); + code += 1 + LINK_SIZE; + len += 1 + LINK_SIZE; + tempcode[0] = OP_ONCE; + *code++ = OP_KET; + PUTINC(code, 0, len); + PUT(tempcode, 1, len); + break; + } + } + + /* In all case we no longer have a previous item. We also set the + "follows varying string" flag for subsequently encountered reqchars if + it isn't already set and we have just passed a varying length item. */ + + END_REPEAT: + previous = NULL; + cd->req_varyopt |= reqvary; + break; + + + /* ===================================================================*/ + /* Start of nested parenthesized sub-expression, or comment or lookahead or + lookbehind or option setting or condition or all the other extended + parenthesis forms. */ + + case CHAR_LEFT_PARENTHESIS: + newoptions = options; + skipbytes = 0; + bravalue = OP_CBRA; + save_hwm = cd->hwm; + reset_bracount = FALSE; + + /* First deal with various "verbs" that can be introduced by '*'. */ + + ptr++; + if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':' + || (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0)))) + { + int i, namelen; + int arglen = 0; + const char *vn = verbnames; + const pcre_uchar *name = ptr + 1; + const pcre_uchar *arg = NULL; + previous = NULL; + ptr++; + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_letter) != 0) ptr++; + namelen = (int)(ptr - name); + + /* It appears that Perl allows any characters whatsoever, other than + a closing parenthesis, to appear in arguments, so we no longer insist on + letters, digits, and underscores. */ + + if (*ptr == CHAR_COLON) + { + arg = ++ptr; + while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; + arglen = (int)(ptr - arg); + } + + if (*ptr != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR60; + goto FAILED; + } + + /* Scan the table of verb names */ + + for (i = 0; i < verbcount; i++) + { + if (namelen == verbs[i].len && + STRNCMP_UC_C8(name, vn, namelen) == 0) + { + /* Check for open captures before ACCEPT and convert it to + ASSERT_ACCEPT if in an assertion. */ + + if (verbs[i].op == OP_ACCEPT) + { + open_capitem *oc; + if (arglen != 0) + { + *errorcodeptr = ERR59; + goto FAILED; + } + cd->had_accept = TRUE; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + *code++ = OP_CLOSE; + PUT2INC(code, 0, oc->number); + } + *code++ = (cd->assert_depth > 0)? OP_ASSERT_ACCEPT : OP_ACCEPT; + + /* Do not set firstchar after *ACCEPT */ + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + } + + /* Handle other cases with/without an argument */ + + else if (arglen == 0) + { + if (verbs[i].op < 0) /* Argument is mandatory */ + { + *errorcodeptr = ERR66; + goto FAILED; + } + *code = verbs[i].op; + if (*code++ == OP_THEN) cd->external_flags |= PCRE_HASTHEN; + } + + else + { + if (verbs[i].op_arg < 0) /* Argument is forbidden */ + { + *errorcodeptr = ERR59; + goto FAILED; + } + *code = verbs[i].op_arg; + if (*code++ == OP_THEN_ARG) cd->external_flags |= PCRE_HASTHEN; + *code++ = arglen; + memcpy(code, arg, IN_UCHARS(arglen)); + code += arglen; + *code++ = 0; + } + + break; /* Found verb, exit loop */ + } + + vn += verbs[i].len + 1; + } + + if (i < verbcount) continue; /* Successfully handled a verb */ + *errorcodeptr = ERR60; /* Verb not recognized */ + goto FAILED; + } + + /* Deal with the extended parentheses; all are introduced by '?', and the + appearance of any of them means that this is not a capturing group. */ + + else if (*ptr == CHAR_QUESTION_MARK) + { + int i, set, unset, namelen; + int *optset; + const pcre_uchar *name; + pcre_uchar *slot; + + switch (*(++ptr)) + { + case CHAR_NUMBER_SIGN: /* Comment; skip to ket */ + ptr++; + while (*ptr != 0 && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++; + if (*ptr == 0) + { + *errorcodeptr = ERR18; + goto FAILED; + } + continue; + + + /* ------------------------------------------------------------ */ + case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ + reset_bracount = TRUE; + /* Fall through */ + + /* ------------------------------------------------------------ */ + case CHAR_COLON: /* Non-capturing bracket */ + bravalue = OP_BRA; + ptr++; + break; + + + /* ------------------------------------------------------------ */ + case CHAR_LEFT_PARENTHESIS: + bravalue = OP_COND; /* Conditional group */ + + /* A condition can be an assertion, a number (referring to a numbered + group), a name (referring to a named group), or 'R', referring to + recursion. R and R&name are also permitted for recursion tests. + + There are several syntaxes for testing a named group: (?(name)) is used + by Python; Perl 5.10 onwards uses (?() or (?('name')). + + There are two unfortunate ambiguities, caused by history. (a) 'R' can + be the recursive thing or the name 'R' (and similarly for 'R' followed + by digits), and (b) a number could be a name that consists of digits. + In both cases, we look for a name first; if not found, we try the other + cases. */ + + /* For conditions that are assertions, check the syntax, and then exit + the switch. This will take control down to where bracketed groups, + including assertions, are processed. */ + + if (ptr[1] == CHAR_QUESTION_MARK && (ptr[2] == CHAR_EQUALS_SIGN || + ptr[2] == CHAR_EXCLAMATION_MARK || ptr[2] == CHAR_LESS_THAN_SIGN)) + break; + + /* Most other conditions use OP_CREF (a couple change to OP_RREF + below), and all need to skip 1+IMM2_SIZE bytes at the start of the group. */ + + code[1+LINK_SIZE] = OP_CREF; + skipbytes = 1+IMM2_SIZE; + refsign = -1; + + /* Check for a test for recursion in a named group. */ + + if (ptr[1] == CHAR_R && ptr[2] == CHAR_AMPERSAND) + { + terminator = -1; + ptr += 2; + code[1+LINK_SIZE] = OP_RREF; /* Change the type of test */ + } + + /* Check for a test for a named group's having been set, using the Perl + syntax (?() or (?('name') */ + + else if (ptr[1] == CHAR_LESS_THAN_SIGN) + { + terminator = CHAR_GREATER_THAN_SIGN; + ptr++; + } + else if (ptr[1] == CHAR_APOSTROPHE) + { + terminator = CHAR_APOSTROPHE; + ptr++; + } + else + { + terminator = 0; + if (ptr[1] == CHAR_MINUS || ptr[1] == CHAR_PLUS) refsign = *(++ptr); + } + + /* We now expect to read a name; any thing else is an error */ + + if (!MAX_255(ptr[1]) || (cd->ctypes[ptr[1]] & ctype_word) == 0) + { + ptr += 1; /* To get the right offset */ + *errorcodeptr = ERR28; + goto FAILED; + } + + /* Read the name, but also get it as a number if it's all digits */ + + recno = 0; + name = ++ptr; + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) + { + if (recno >= 0) + recno = (IS_DIGIT(*ptr))? recno * 10 + *ptr - CHAR_0 : -1; + ptr++; + } + namelen = (int)(ptr - name); + + if ((terminator > 0 && *ptr++ != terminator) || + *ptr++ != CHAR_RIGHT_PARENTHESIS) + { + ptr--; /* Error offset */ + *errorcodeptr = ERR26; + goto FAILED; + } + + /* Do no further checking in the pre-compile phase. */ + + if (lengthptr != NULL) break; + + /* In the real compile we do the work of looking for the actual + reference. If the string started with "+" or "-" we require the rest to + be digits, in which case recno will be set. */ + + if (refsign > 0) + { + if (recno <= 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + recno = (refsign == CHAR_MINUS)? + cd->bracount - recno + 1 : recno +cd->bracount; + if (recno <= 0 || recno > cd->final_bracount) + { + *errorcodeptr = ERR15; + goto FAILED; + } + PUT2(code, 2+LINK_SIZE, recno); + break; + } + + /* Otherwise (did not start with "+" or "-"), start by looking for the + name. If we find a name, add one to the opcode to change OP_CREF or + OP_RREF into OP_NCREF or OP_NRREF. These behave exactly the same, + except they record that the reference was originally to a name. The + information is used to check duplicate names. */ + + slot = cd->name_table; + for (i = 0; i < cd->names_found; i++) + { + if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0) break; + slot += cd->name_entry_size; + } + + /* Found a previous named subpattern */ + + if (i < cd->names_found) + { + recno = GET2(slot, 0); + PUT2(code, 2+LINK_SIZE, recno); + code[1+LINK_SIZE]++; + } + + /* Search the pattern for a forward reference */ + + else if ((i = find_parens(cd, name, namelen, + (options & PCRE_EXTENDED) != 0, utf)) > 0) + { + PUT2(code, 2+LINK_SIZE, i); + code[1+LINK_SIZE]++; + } + + /* If terminator == 0 it means that the name followed directly after + the opening parenthesis [e.g. (?(abc)...] and in this case there are + some further alternatives to try. For the cases where terminator != 0 + [things like (?(... or (?('name')... or (?(R&name)... ] we have + now checked all the possibilities, so give an error. */ + + else if (terminator != 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + + /* Check for (?(R) for recursion. Allow digits after R to specify a + specific group number. */ + + else if (*name == CHAR_R) + { + recno = 0; + for (i = 1; i < namelen; i++) + { + if (!IS_DIGIT(name[i])) + { + *errorcodeptr = ERR15; + goto FAILED; + } + recno = recno * 10 + name[i] - CHAR_0; + } + if (recno == 0) recno = RREF_ANY; + code[1+LINK_SIZE] = OP_RREF; /* Change test type */ + PUT2(code, 2+LINK_SIZE, recno); + } + + /* Similarly, check for the (?(DEFINE) "condition", which is always + false. */ + + else if (namelen == 6 && STRNCMP_UC_C8(name, STRING_DEFINE, 6) == 0) + { + code[1+LINK_SIZE] = OP_DEF; + skipbytes = 1; + } + + /* Check for the "name" actually being a subpattern number. We are + in the second pass here, so final_bracount is set. */ + + else if (recno > 0 && recno <= cd->final_bracount) + { + PUT2(code, 2+LINK_SIZE, recno); + } + + /* Either an unidentified subpattern, or a reference to (?(0) */ + + else + { + *errorcodeptr = (recno == 0)? ERR35: ERR15; + goto FAILED; + } + break; + + + /* ------------------------------------------------------------ */ + case CHAR_EQUALS_SIGN: /* Positive lookahead */ + bravalue = OP_ASSERT; + cd->assert_depth += 1; + ptr++; + break; + + + /* ------------------------------------------------------------ */ + case CHAR_EXCLAMATION_MARK: /* Negative lookahead */ + ptr++; + if (*ptr == CHAR_RIGHT_PARENTHESIS) /* Optimize (?!) */ + { + *code++ = OP_FAIL; + previous = NULL; + continue; + } + bravalue = OP_ASSERT_NOT; + cd->assert_depth += 1; + break; + + + /* ------------------------------------------------------------ */ + case CHAR_LESS_THAN_SIGN: /* Lookbehind or named define */ + switch (ptr[1]) + { + case CHAR_EQUALS_SIGN: /* Positive lookbehind */ + bravalue = OP_ASSERTBACK; + cd->assert_depth += 1; + ptr += 2; + break; + + case CHAR_EXCLAMATION_MARK: /* Negative lookbehind */ + bravalue = OP_ASSERTBACK_NOT; + cd->assert_depth += 1; + ptr += 2; + break; + + default: /* Could be name define, else bad */ + if (MAX_255(ptr[1]) && (cd->ctypes[ptr[1]] & ctype_word) != 0) + goto DEFINE_NAME; + ptr++; /* Correct offset for error */ + *errorcodeptr = ERR24; + goto FAILED; + } + break; + + + /* ------------------------------------------------------------ */ + case CHAR_GREATER_THAN_SIGN: /* One-time brackets */ + bravalue = OP_ONCE; + ptr++; + break; + + + /* ------------------------------------------------------------ */ + case CHAR_C: /* Callout - may be followed by digits; */ + previous_callout = code; /* Save for later completion */ + after_manual_callout = 1; /* Skip one item before completing */ + *code++ = OP_CALLOUT; + { + int n = 0; + ptr++; + while(IS_DIGIT(*ptr)) + n = n * 10 + *ptr++ - CHAR_0; + if (*ptr != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR39; + goto FAILED; + } + if (n > 255) + { + *errorcodeptr = ERR38; + goto FAILED; + } + *code++ = n; + PUT(code, 0, (int)(ptr - cd->start_pattern + 1)); /* Pattern offset */ + PUT(code, LINK_SIZE, 0); /* Default length */ + code += 2 * LINK_SIZE; + } + previous = NULL; + continue; + + + /* ------------------------------------------------------------ */ + case CHAR_P: /* Python-style named subpattern handling */ + if (*(++ptr) == CHAR_EQUALS_SIGN || + *ptr == CHAR_GREATER_THAN_SIGN) /* Reference or recursion */ + { + is_recurse = *ptr == CHAR_GREATER_THAN_SIGN; + terminator = CHAR_RIGHT_PARENTHESIS; + goto NAMED_REF_OR_RECURSE; + } + else if (*ptr != CHAR_LESS_THAN_SIGN) /* Test for Python-style defn */ + { + *errorcodeptr = ERR41; + goto FAILED; + } + /* Fall through to handle (?P< as (?< is handled */ + + + /* ------------------------------------------------------------ */ + DEFINE_NAME: /* Come here from (?< handling */ + case CHAR_APOSTROPHE: + { + terminator = (*ptr == CHAR_LESS_THAN_SIGN)? + CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; + name = ++ptr; + + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; + namelen = (int)(ptr - name); + + /* In the pre-compile phase, just do a syntax check. */ + + if (lengthptr != NULL) + { + if (*ptr != terminator) + { + *errorcodeptr = ERR42; + goto FAILED; + } + if (cd->names_found >= MAX_NAME_COUNT) + { + *errorcodeptr = ERR49; + goto FAILED; + } + if (namelen + IMM2_SIZE + 1 > cd->name_entry_size) + { + cd->name_entry_size = namelen + IMM2_SIZE + 1; + if (namelen > MAX_NAME_SIZE) + { + *errorcodeptr = ERR48; + goto FAILED; + } + } + } + + /* In the real compile, create the entry in the table, maintaining + alphabetical order. Duplicate names for different numbers are + permitted only if PCRE_DUPNAMES is set. Duplicate names for the same + number are always OK. (An existing number can be re-used if (?| + appears in the pattern.) In either event, a duplicate name results in + a duplicate entry in the table, even if the number is the same. This + is because the number of names, and hence the table size, is computed + in the pre-compile, and it affects various numbers and pointers which + would all have to be modified, and the compiled code moved down, if + duplicates with the same number were omitted from the table. This + doesn't seem worth the hassle. However, *different* names for the + same number are not permitted. */ + + else + { + BOOL dupname = FALSE; + slot = cd->name_table; + + for (i = 0; i < cd->names_found; i++) + { + int crc = memcmp(name, slot+IMM2_SIZE, IN_UCHARS(namelen)); + if (crc == 0) + { + if (slot[IMM2_SIZE+namelen] == 0) + { + if (GET2(slot, 0) != cd->bracount + 1 && + (options & PCRE_DUPNAMES) == 0) + { + *errorcodeptr = ERR43; + goto FAILED; + } + else dupname = TRUE; + } + else crc = -1; /* Current name is a substring */ + } + + /* Make space in the table and break the loop for an earlier + name. For a duplicate or later name, carry on. We do this for + duplicates so that in the simple case (when ?(| is not used) they + are in order of their numbers. */ + + if (crc < 0) + { + memmove(slot + cd->name_entry_size, slot, + IN_UCHARS((cd->names_found - i) * cd->name_entry_size)); + break; + } + + /* Continue the loop for a later or duplicate name */ + + slot += cd->name_entry_size; + } + + /* For non-duplicate names, check for a duplicate number before + adding the new name. */ + + if (!dupname) + { + pcre_uchar *cslot = cd->name_table; + for (i = 0; i < cd->names_found; i++) + { + if (cslot != slot) + { + if (GET2(cslot, 0) == cd->bracount + 1) + { + *errorcodeptr = ERR65; + goto FAILED; + } + } + else i--; + cslot += cd->name_entry_size; + } + } + + PUT2(slot, 0, cd->bracount + 1); + memcpy(slot + IMM2_SIZE, name, IN_UCHARS(namelen)); + slot[IMM2_SIZE + namelen] = 0; + } + } + + /* In both pre-compile and compile, count the number of names we've + encountered. */ + + cd->names_found++; + ptr++; /* Move past > or ' */ + goto NUMBERED_GROUP; + + + /* ------------------------------------------------------------ */ + case CHAR_AMPERSAND: /* Perl recursion/subroutine syntax */ + terminator = CHAR_RIGHT_PARENTHESIS; + is_recurse = TRUE; + /* Fall through */ + + /* We come here from the Python syntax above that handles both + references (?P=name) and recursion (?P>name), as well as falling + through from the Perl recursion syntax (?&name). We also come here from + the Perl \k or \k'name' back reference syntax and the \k{name} + .NET syntax, and the Oniguruma \g<...> and \g'...' subroutine syntax. */ + + NAMED_REF_OR_RECURSE: + name = ++ptr; + while (MAX_255(*ptr) && (cd->ctypes[*ptr] & ctype_word) != 0) ptr++; + namelen = (int)(ptr - name); + + /* In the pre-compile phase, do a syntax check. We used to just set + a dummy reference number, because it was not used in the first pass. + However, with the change of recursive back references to be atomic, + we have to look for the number so that this state can be identified, as + otherwise the incorrect length is computed. If it's not a backwards + reference, the dummy number will do. */ + + if (lengthptr != NULL) + { + const pcre_uchar *temp; + + if (namelen == 0) + { + *errorcodeptr = ERR62; + goto FAILED; + } + if (*ptr != terminator) + { + *errorcodeptr = ERR42; + goto FAILED; + } + if (namelen > MAX_NAME_SIZE) + { + *errorcodeptr = ERR48; + goto FAILED; + } + + /* The name table does not exist in the first pass, so we cannot + do a simple search as in the code below. Instead, we have to scan the + pattern to find the number. It is important that we scan it only as + far as we have got because the syntax of named subpatterns has not + been checked for the rest of the pattern, and find_parens() assumes + correct syntax. In any case, it's a waste of resources to scan + further. We stop the scan at the current point by temporarily + adjusting the value of cd->endpattern. */ + + temp = cd->end_pattern; + cd->end_pattern = ptr; + recno = find_parens(cd, name, namelen, + (options & PCRE_EXTENDED) != 0, utf); + cd->end_pattern = temp; + if (recno < 0) recno = 0; /* Forward ref; set dummy number */ + } + + /* In the real compile, seek the name in the table. We check the name + first, and then check that we have reached the end of the name in the + table. That way, if the name that is longer than any in the table, + the comparison will fail without reading beyond the table entry. */ + + else + { + slot = cd->name_table; + for (i = 0; i < cd->names_found; i++) + { + if (STRNCMP_UC_UC(name, slot+IMM2_SIZE, namelen) == 0 && + slot[IMM2_SIZE+namelen] == 0) + break; + slot += cd->name_entry_size; + } + + if (i < cd->names_found) /* Back reference */ + { + recno = GET2(slot, 0); + } + else if ((recno = /* Forward back reference */ + find_parens(cd, name, namelen, + (options & PCRE_EXTENDED) != 0, utf)) <= 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + } + + /* In both phases, we can now go to the code than handles numerical + recursion or backreferences. */ + + if (is_recurse) goto HANDLE_RECURSION; + else goto HANDLE_REFERENCE; + + + /* ------------------------------------------------------------ */ + case CHAR_R: /* Recursion */ + ptr++; /* Same as (?0) */ + /* Fall through */ + + + /* ------------------------------------------------------------ */ + case CHAR_MINUS: case CHAR_PLUS: /* Recursion or subroutine */ + case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4: + case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9: + { + const pcre_uchar *called; + terminator = CHAR_RIGHT_PARENTHESIS; + + /* Come here from the \g<...> and \g'...' code (Oniguruma + compatibility). However, the syntax has been checked to ensure that + the ... are a (signed) number, so that neither ERR63 nor ERR29 will + be called on this path, nor with the jump to OTHER_CHAR_AFTER_QUERY + ever be taken. */ + + HANDLE_NUMERICAL_RECURSION: + + if ((refsign = *ptr) == CHAR_PLUS) + { + ptr++; + if (!IS_DIGIT(*ptr)) + { + *errorcodeptr = ERR63; + goto FAILED; + } + } + else if (refsign == CHAR_MINUS) + { + if (!IS_DIGIT(ptr[1])) + goto OTHER_CHAR_AFTER_QUERY; + ptr++; + } + + recno = 0; + while(IS_DIGIT(*ptr)) + recno = recno * 10 + *ptr++ - CHAR_0; + + if (*ptr != terminator) + { + *errorcodeptr = ERR29; + goto FAILED; + } + + if (refsign == CHAR_MINUS) + { + if (recno == 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + recno = cd->bracount - recno + 1; + if (recno <= 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + } + else if (refsign == CHAR_PLUS) + { + if (recno == 0) + { + *errorcodeptr = ERR58; + goto FAILED; + } + recno += cd->bracount; + } + + /* Come here from code above that handles a named recursion */ + + HANDLE_RECURSION: + + previous = code; + called = cd->start_code; + + /* When we are actually compiling, find the bracket that is being + referenced. Temporarily end the regex in case it doesn't exist before + this point. If we end up with a forward reference, first check that + the bracket does occur later so we can give the error (and position) + now. Then remember this forward reference in the workspace so it can + be filled in at the end. */ + + if (lengthptr == NULL) + { + *code = OP_END; + if (recno != 0) + called = PRIV(find_bracket)(cd->start_code, utf, recno); + + /* Forward reference */ + + if (called == NULL) + { + if (find_parens(cd, NULL, recno, + (options & PCRE_EXTENDED) != 0, utf) < 0) + { + *errorcodeptr = ERR15; + goto FAILED; + } + + /* Fudge the value of "called" so that when it is inserted as an + offset below, what it actually inserted is the reference number + of the group. Then remember the forward reference. */ + + called = cd->start_code + recno; + if (cd->hwm >= cd->start_workspace + cd->workspace_size - + WORK_SIZE_SAFETY_MARGIN) + { + *errorcodeptr = expand_workspace(cd); + if (*errorcodeptr != 0) goto FAILED; + } + PUTINC(cd->hwm, 0, (int)(code + 1 - cd->start_code)); + } + + /* If not a forward reference, and the subpattern is still open, + this is a recursive call. We check to see if this is a left + recursion that could loop for ever, and diagnose that case. We + must not, however, do this check if we are in a conditional + subpattern because the condition might be testing for recursion in + a pattern such as /(?(R)a+|(?R)b)/, which is perfectly valid. + Forever loops are also detected at runtime, so those that occur in + conditional subpatterns will be picked up then. */ + + else if (GET(called, 1) == 0 && cond_depth <= 0 && + could_be_empty(called, code, bcptr, utf, cd)) + { + *errorcodeptr = ERR40; + goto FAILED; + } + } + + /* Insert the recursion/subroutine item. It does not have a set first + character (relevant if it is repeated, because it will then be + wrapped with ONCE brackets). */ + + *code = OP_RECURSE; + PUT(code, 1, (int)(called - cd->start_code)); + code += 1 + LINK_SIZE; + groupsetfirstchar = FALSE; + } + + /* Can't determine a first byte now */ + + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + continue; + + + /* ------------------------------------------------------------ */ + default: /* Other characters: check option setting */ + OTHER_CHAR_AFTER_QUERY: + set = unset = 0; + optset = &set; + + while (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_COLON) + { + switch (*ptr++) + { + case CHAR_MINUS: optset = &unset; break; + + case CHAR_J: /* Record that it changed in the external options */ + *optset |= PCRE_DUPNAMES; + cd->external_flags |= PCRE_JCHANGED; + break; + + case CHAR_i: *optset |= PCRE_CASELESS; break; + case CHAR_m: *optset |= PCRE_MULTILINE; break; + case CHAR_s: *optset |= PCRE_DOTALL; break; + case CHAR_x: *optset |= PCRE_EXTENDED; break; + case CHAR_U: *optset |= PCRE_UNGREEDY; break; + case CHAR_X: *optset |= PCRE_EXTRA; break; + + default: *errorcodeptr = ERR12; + ptr--; /* Correct the offset */ + goto FAILED; + } + } + + /* Set up the changed option bits, but don't change anything yet. */ + + newoptions = (options | set) & (~unset); + + /* If the options ended with ')' this is not the start of a nested + group with option changes, so the options change at this level. If this + item is right at the start of the pattern, the options can be + abstracted and made external in the pre-compile phase, and ignored in + the compile phase. This can be helpful when matching -- for instance in + caseless checking of required bytes. + + If the code pointer is not (cd->start_code + 1 + LINK_SIZE), we are + definitely *not* at the start of the pattern because something has been + compiled. In the pre-compile phase, however, the code pointer can have + that value after the start, because it gets reset as code is discarded + during the pre-compile. However, this can happen only at top level - if + we are within parentheses, the starting BRA will still be present. At + any parenthesis level, the length value can be used to test if anything + has been compiled at that level. Thus, a test for both these conditions + is necessary to ensure we correctly detect the start of the pattern in + both phases. + + If we are not at the pattern start, reset the greedy defaults and the + case value for firstchar and reqchar. */ + + if (*ptr == CHAR_RIGHT_PARENTHESIS) + { + if (code == cd->start_code + 1 + LINK_SIZE && + (lengthptr == NULL || *lengthptr == 2 + 2*LINK_SIZE)) + { + cd->external_options = newoptions; + } + else + { + greedy_default = ((newoptions & PCRE_UNGREEDY) != 0); + greedy_non_default = greedy_default ^ 1; + req_caseopt = ((newoptions & PCRE_CASELESS) != 0)? REQ_CASELESS:0; + } + + /* Change options at this level, and pass them back for use + in subsequent branches. */ + + *optionsptr = options = newoptions; + previous = NULL; /* This item can't be repeated */ + continue; /* It is complete */ + } + + /* If the options ended with ':' we are heading into a nested group + with possible change of options. Such groups are non-capturing and are + not assertions of any kind. All we need to do is skip over the ':'; + the newoptions value is handled below. */ + + bravalue = OP_BRA; + ptr++; + } /* End of switch for character following (? */ + } /* End of (? handling */ + + /* Opening parenthesis not followed by '*' or '?'. If PCRE_NO_AUTO_CAPTURE + is set, all unadorned brackets become non-capturing and behave like (?:...) + brackets. */ + + else if ((options & PCRE_NO_AUTO_CAPTURE) != 0) + { + bravalue = OP_BRA; + } + + /* Else we have a capturing group. */ + + else + { + NUMBERED_GROUP: + cd->bracount += 1; + PUT2(code, 1+LINK_SIZE, cd->bracount); + skipbytes = IMM2_SIZE; + } + + /* Process nested bracketed regex. Assertions used not to be repeatable, + but this was changed for Perl compatibility, so all kinds can now be + repeated. We copy code into a non-register variable (tempcode) in order to + be able to pass its address because some compilers complain otherwise. */ + + previous = code; /* For handling repetition */ + *code = bravalue; + tempcode = code; + tempreqvary = cd->req_varyopt; /* Save value before bracket */ + tempbracount = cd->bracount; /* Save value before bracket */ + length_prevgroup = 0; /* Initialize for pre-compile phase */ + + if (!compile_regex( + newoptions, /* The complete new option state */ + &tempcode, /* Where to put code (updated) */ + &ptr, /* Input pointer (updated) */ + errorcodeptr, /* Where to put an error message */ + (bravalue == OP_ASSERTBACK || + bravalue == OP_ASSERTBACK_NOT), /* TRUE if back assert */ + reset_bracount, /* True if (?| group */ + skipbytes, /* Skip over bracket number */ + cond_depth + + ((bravalue == OP_COND)?1:0), /* Depth of condition subpatterns */ + &subfirstchar, /* For possible first char */ + &subreqchar, /* For possible last char */ + bcptr, /* Current branch chain */ + cd, /* Tables block */ + (lengthptr == NULL)? NULL : /* Actual compile phase */ + &length_prevgroup /* Pre-compile phase */ + )) + goto FAILED; + + /* If this was an atomic group and there are no capturing groups within it, + generate OP_ONCE_NC instead of OP_ONCE. */ + + if (bravalue == OP_ONCE && cd->bracount <= tempbracount) + *code = OP_ONCE_NC; + + if (bravalue >= OP_ASSERT && bravalue <= OP_ASSERTBACK_NOT) + cd->assert_depth -= 1; + + /* At the end of compiling, code is still pointing to the start of the + group, while tempcode has been updated to point past the end of the group. + The pattern pointer (ptr) is on the bracket. + + If this is a conditional bracket, check that there are no more than + two branches in the group, or just one if it's a DEFINE group. We do this + in the real compile phase, not in the pre-pass, where the whole group may + not be available. */ + + if (bravalue == OP_COND && lengthptr == NULL) + { + pcre_uchar *tc = code; + int condcount = 0; + + do { + condcount++; + tc += GET(tc,1); + } + while (*tc != OP_KET); + + /* A DEFINE group is never obeyed inline (the "condition" is always + false). It must have only one branch. */ + + if (code[LINK_SIZE+1] == OP_DEF) + { + if (condcount > 1) + { + *errorcodeptr = ERR54; + goto FAILED; + } + bravalue = OP_DEF; /* Just a flag to suppress char handling below */ + } + + /* A "normal" conditional group. If there is just one branch, we must not + make use of its firstchar or reqchar, because this is equivalent to an + empty second branch. */ + + else + { + if (condcount > 2) + { + *errorcodeptr = ERR27; + goto FAILED; + } + if (condcount == 1) subfirstchar = subreqchar = REQ_NONE; + } + } + + /* Error if hit end of pattern */ + + if (*ptr != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR14; + goto FAILED; + } + + /* In the pre-compile phase, update the length by the length of the group, + less the brackets at either end. Then reduce the compiled code to just a + set of non-capturing brackets so that it doesn't use much memory if it is + duplicated by a quantifier.*/ + + if (lengthptr != NULL) + { + if (OFLOW_MAX - *lengthptr < length_prevgroup - 2 - 2*LINK_SIZE) + { + *errorcodeptr = ERR20; + goto FAILED; + } + *lengthptr += length_prevgroup - 2 - 2*LINK_SIZE; + code++; /* This already contains bravalue */ + PUTINC(code, 0, 1 + LINK_SIZE); + *code++ = OP_KET; + PUTINC(code, 0, 1 + LINK_SIZE); + break; /* No need to waste time with special character handling */ + } + + /* Otherwise update the main code pointer to the end of the group. */ + + code = tempcode; + + /* For a DEFINE group, required and first character settings are not + relevant. */ + + if (bravalue == OP_DEF) break; + + /* Handle updating of the required and first characters for other types of + group. Update for normal brackets of all kinds, and conditions with two + branches (see code above). If the bracket is followed by a quantifier with + zero repeat, we have to back off. Hence the definition of zeroreqchar and + zerofirstchar outside the main loop so that they can be accessed for the + back off. */ + + zeroreqchar = reqchar; + zerofirstchar = firstchar; + groupsetfirstchar = FALSE; + + if (bravalue >= OP_ONCE) + { + /* If we have not yet set a firstchar in this branch, take it from the + subpattern, remembering that it was set here so that a repeat of more + than one can replicate it as reqchar if necessary. If the subpattern has + no firstchar, set "none" for the whole branch. In both cases, a zero + repeat forces firstchar to "none". */ + + if (firstchar == REQ_UNSET) + { + if (subfirstchar >= 0) + { + firstchar = subfirstchar; + groupsetfirstchar = TRUE; + } + else firstchar = REQ_NONE; + zerofirstchar = REQ_NONE; + } + + /* If firstchar was previously set, convert the subpattern's firstchar + into reqchar if there wasn't one, using the vary flag that was in + existence beforehand. */ + + else if (subfirstchar >= 0 && subreqchar < 0) + subreqchar = subfirstchar | tempreqvary; + + /* If the subpattern set a required byte (or set a first byte that isn't + really the first byte - see above), set it. */ + + if (subreqchar >= 0) reqchar = subreqchar; + } + + /* For a forward assertion, we take the reqchar, if set. This can be + helpful if the pattern that follows the assertion doesn't set a different + char. For example, it's useful for /(?=abcde).+/. We can't set firstchar + for an assertion, however because it leads to incorrect effect for patterns + such as /(?=a)a.+/ when the "real" "a" would then become a reqchar instead + of a firstchar. This is overcome by a scan at the end if there's no + firstchar, looking for an asserted first char. */ + + else if (bravalue == OP_ASSERT && subreqchar >= 0) reqchar = subreqchar; + break; /* End of processing '(' */ + + + /* ===================================================================*/ + /* Handle metasequences introduced by \. For ones like \d, the ESC_ values + are arranged to be the negation of the corresponding OP_values in the + default case when PCRE_UCP is not set. For the back references, the values + are ESC_REF plus the reference number. Only back references and those types + that consume a character may be repeated. We can test for values between + ESC_b and ESC_Z for the latter; this may have to change if any new ones are + ever created. */ + + case CHAR_BACKSLASH: + tempptr = ptr; + c = check_escape(&ptr, errorcodeptr, cd->bracount, options, FALSE); + if (*errorcodeptr != 0) goto FAILED; + + if (c < 0) + { + if (-c == ESC_Q) /* Handle start of quoted string */ + { + if (ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E) + ptr += 2; /* avoid empty string */ + else inescq = TRUE; + continue; + } + + if (-c == ESC_E) continue; /* Perl ignores an orphan \E */ + + /* For metasequences that actually match a character, we disable the + setting of a first character if it hasn't already been set. */ + + if (firstchar == REQ_UNSET && -c > ESC_b && -c < ESC_Z) + firstchar = REQ_NONE; + + /* Set values to reset to if this is followed by a zero repeat. */ + + zerofirstchar = firstchar; + zeroreqchar = reqchar; + + /* \g or \g'name' is a subroutine call by name and \g or \g'n' + is a subroutine call by number (Oniguruma syntax). In fact, the value + -ESC_g is returned only for these cases. So we don't need to check for < + or ' if the value is -ESC_g. For the Perl syntax \g{n} the value is + -ESC_REF+n, and for the Perl syntax \g{name} the result is -ESC_k (as + that is a synonym for a named back reference). */ + + if (-c == ESC_g) + { + const pcre_uchar *p; + save_hwm = cd->hwm; /* Normally this is set when '(' is read */ + terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? + CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; + + /* These two statements stop the compiler for warning about possibly + unset variables caused by the jump to HANDLE_NUMERICAL_RECURSION. In + fact, because we actually check for a number below, the paths that + would actually be in error are never taken. */ + + skipbytes = 0; + reset_bracount = FALSE; + + /* Test for a name */ + + if (ptr[1] != CHAR_PLUS && ptr[1] != CHAR_MINUS) + { + BOOL is_a_number = TRUE; + for (p = ptr + 1; *p != 0 && *p != terminator; p++) + { + if (!MAX_255(*p)) { is_a_number = FALSE; break; } + if ((cd->ctypes[*p] & ctype_digit) == 0) is_a_number = FALSE; + if ((cd->ctypes[*p] & ctype_word) == 0) break; + } + if (*p != terminator) + { + *errorcodeptr = ERR57; + break; + } + if (is_a_number) + { + ptr++; + goto HANDLE_NUMERICAL_RECURSION; + } + is_recurse = TRUE; + goto NAMED_REF_OR_RECURSE; + } + + /* Test a signed number in angle brackets or quotes. */ + + p = ptr + 2; + while (IS_DIGIT(*p)) p++; + if (*p != terminator) + { + *errorcodeptr = ERR57; + break; + } + ptr++; + goto HANDLE_NUMERICAL_RECURSION; + } + + /* \k or \k'name' is a back reference by name (Perl syntax). + We also support \k{name} (.NET syntax). */ + + if (-c == ESC_k) + { + if ((ptr[1] != CHAR_LESS_THAN_SIGN && + ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) + { + *errorcodeptr = ERR69; + break; + } + is_recurse = FALSE; + terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? + CHAR_GREATER_THAN_SIGN : (*ptr == CHAR_APOSTROPHE)? + CHAR_APOSTROPHE : CHAR_RIGHT_CURLY_BRACKET; + goto NAMED_REF_OR_RECURSE; + } + + /* Back references are handled specially; must disable firstchar if + not set to cope with cases like (?=(\w+))\1: which would otherwise set + ':' later. */ + + if (-c >= ESC_REF) + { + open_capitem *oc; + recno = -c - ESC_REF; + + HANDLE_REFERENCE: /* Come here from named backref handling */ + if (firstchar == REQ_UNSET) firstchar = REQ_NONE; + previous = code; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; + PUT2INC(code, 0, recno); + cd->backref_map |= (recno < 32)? (1 << recno) : 1; + if (recno > cd->top_backref) cd->top_backref = recno; + + /* Check to see if this back reference is recursive, that it, it + is inside the group that it references. A flag is set so that the + group can be made atomic. */ + + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + if (oc->number == recno) + { + oc->flag = TRUE; + break; + } + } + } + + /* So are Unicode property matches, if supported. */ + +#ifdef SUPPORT_UCP + else if (-c == ESC_P || -c == ESC_p) + { + BOOL negated; + int pdata; + int ptype = get_ucp(&ptr, &negated, &pdata, errorcodeptr); + if (ptype < 0) goto FAILED; + previous = code; + *code++ = ((-c == ESC_p) != negated)? OP_PROP : OP_NOTPROP; + *code++ = ptype; + *code++ = pdata; + } +#else + + /* If Unicode properties are not supported, \X, \P, and \p are not + allowed. */ + + else if (-c == ESC_X || -c == ESC_P || -c == ESC_p) + { + *errorcodeptr = ERR45; + goto FAILED; + } +#endif + + /* For the rest (including \X when Unicode properties are supported), we + can obtain the OP value by negating the escape value in the default + situation when PCRE_UCP is not set. When it *is* set, we substitute + Unicode property tests. */ + + else + { +#ifdef SUPPORT_UCP + if (-c >= ESC_DU && -c <= ESC_wu) + { + nestptr = ptr + 1; /* Where to resume */ + ptr = substitutes[-c - ESC_DU] - 1; /* Just before substitute */ + } + else +#endif + /* In non-UTF-8 mode, we turn \C into OP_ALLANY instead of OP_ANYBYTE + so that it works in DFA mode and in lookbehinds. */ + + { + previous = (-c > ESC_b && -c < ESC_Z)? code : NULL; + *code++ = (!utf && c == -ESC_C)? OP_ALLANY : -c; + } + } + continue; + } + + /* We have a data character whose value is in c. In UTF-8 mode it may have + a value > 127. We set its representation in the length/buffer, and then + handle it as a data character. */ + +#ifdef SUPPORT_UTF + if (utf && c > MAX_VALUE_FOR_SINGLE_CHAR) + mclength = PRIV(ord2utf)(c, mcbuffer); + else +#endif + + { + mcbuffer[0] = c; + mclength = 1; + } + goto ONE_CHAR; + + + /* ===================================================================*/ + /* Handle a literal character. It is guaranteed not to be whitespace or # + when the extended flag is set. If we are in UTF-8 mode, it may be a + multi-byte literal character. */ + + default: + NORMAL_CHAR: + mclength = 1; + mcbuffer[0] = c; + +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(c)) + ACROSSCHAR(TRUE, ptr[1], mcbuffer[mclength++] = *(++ptr)); +#endif + + /* At this point we have the character's bytes in mcbuffer, and the length + in mclength. When not in UTF-8 mode, the length is always 1. */ + + ONE_CHAR: + previous = code; + *code++ = ((options & PCRE_CASELESS) != 0)? OP_CHARI : OP_CHAR; + for (c = 0; c < mclength; c++) *code++ = mcbuffer[c]; + + /* Remember if \r or \n were seen */ + + if (mcbuffer[0] == CHAR_CR || mcbuffer[0] == CHAR_NL) + cd->external_flags |= PCRE_HASCRORLF; + + /* Set the first and required bytes appropriately. If no previous first + byte, set it from this character, but revert to none on a zero repeat. + Otherwise, leave the firstchar value alone, and don't change it on a zero + repeat. */ + + if (firstchar == REQ_UNSET) + { + zerofirstchar = REQ_NONE; + zeroreqchar = reqchar; + + /* If the character is more than one byte long, we can set firstchar + only if it is not to be matched caselessly. */ + + if (mclength == 1 || req_caseopt == 0) + { + firstchar = mcbuffer[0] | req_caseopt; + if (mclength != 1) reqchar = code[-1] | cd->req_varyopt; + } + else firstchar = reqchar = REQ_NONE; + } + + /* firstchar was previously set; we can set reqchar only if the length is + 1 or the matching is caseful. */ + + else + { + zerofirstchar = firstchar; + zeroreqchar = reqchar; + if (mclength == 1 || req_caseopt == 0) + reqchar = code[-1] | req_caseopt | cd->req_varyopt; + } + + break; /* End of literal character handling */ + } + } /* end of big loop */ + + +/* Control never reaches here by falling through, only by a goto for all the +error states. Pass back the position in the pattern so that it can be displayed +to the user for diagnosing the error. */ + +FAILED: +*ptrptr = ptr; +return FALSE; +} + + + + +/************************************************* +* Compile sequence of alternatives * +*************************************************/ + +/* On entry, ptr is pointing past the bracket character, but on return it +points to the closing bracket, or vertical bar, or end of string. The code +variable is pointing at the byte into which the BRA operator has been stored. +This function is used during the pre-compile phase when we are trying to find +out the amount of memory needed, as well as during the real compile phase. The +value of lengthptr distinguishes the two phases. + +Arguments: + options option bits, including any changes for this subpattern + codeptr -> the address of the current code pointer + ptrptr -> the address of the current pattern pointer + errorcodeptr -> pointer to error code variable + lookbehind TRUE if this is a lookbehind assertion + reset_bracount TRUE to reset the count for each branch + skipbytes skip this many bytes at start (for brackets and OP_COND) + cond_depth depth of nesting for conditional subpatterns + firstcharptr place to put the first required character, or a negative number + reqcharptr place to put the last required character, or a negative number + bcptr pointer to the chain of currently open branches + cd points to the data block with tables pointers etc. + lengthptr NULL during the real compile phase + points to length accumulator during pre-compile phase + +Returns: TRUE on success +*/ + +static BOOL +compile_regex(int options, pcre_uchar **codeptr, const pcre_uchar **ptrptr, + int *errorcodeptr, BOOL lookbehind, BOOL reset_bracount, int skipbytes, + int cond_depth, pcre_int32 *firstcharptr, pcre_int32 *reqcharptr, + branch_chain *bcptr, compile_data *cd, int *lengthptr) +{ +const pcre_uchar *ptr = *ptrptr; +pcre_uchar *code = *codeptr; +pcre_uchar *last_branch = code; +pcre_uchar *start_bracket = code; +pcre_uchar *reverse_count = NULL; +open_capitem capitem; +int capnumber = 0; +pcre_int32 firstchar, reqchar; +pcre_int32 branchfirstchar, branchreqchar; +int length; +int orig_bracount; +int max_bracount; +branch_chain bc; + +bc.outer = bcptr; +bc.current_branch = code; + +firstchar = reqchar = REQ_UNSET; + +/* Accumulate the length for use in the pre-compile phase. Start with the +length of the BRA and KET and any extra bytes that are required at the +beginning. We accumulate in a local variable to save frequent testing of +lenthptr for NULL. We cannot do this by looking at the value of code at the +start and end of each alternative, because compiled items are discarded during +the pre-compile phase so that the work space is not exceeded. */ + +length = 2 + 2*LINK_SIZE + skipbytes; + +/* WARNING: If the above line is changed for any reason, you must also change +the code that abstracts option settings at the start of the pattern and makes +them global. It tests the value of length for (2 + 2*LINK_SIZE) in the +pre-compile phase to find out whether anything has yet been compiled or not. */ + +/* If this is a capturing subpattern, add to the chain of open capturing items +so that we can detect them if (*ACCEPT) is encountered. This is also used to +detect groups that contain recursive back references to themselves. Note that +only OP_CBRA need be tested here; changing this opcode to one of its variants, +e.g. OP_SCBRAPOS, happens later, after the group has been compiled. */ + +if (*code == OP_CBRA) + { + capnumber = GET2(code, 1 + LINK_SIZE); + capitem.number = capnumber; + capitem.next = cd->open_caps; + capitem.flag = FALSE; + cd->open_caps = &capitem; + } + +/* Offset is set zero to mark that this bracket is still open */ + +PUT(code, 1, 0); +code += 1 + LINK_SIZE + skipbytes; + +/* Loop for each alternative branch */ + +orig_bracount = max_bracount = cd->bracount; +for (;;) + { + /* For a (?| group, reset the capturing bracket count so that each branch + uses the same numbers. */ + + if (reset_bracount) cd->bracount = orig_bracount; + + /* Set up dummy OP_REVERSE if lookbehind assertion */ + + if (lookbehind) + { + *code++ = OP_REVERSE; + reverse_count = code; + PUTINC(code, 0, 0); + length += 1 + LINK_SIZE; + } + + /* Now compile the branch; in the pre-compile phase its length gets added + into the length. */ + + if (!compile_branch(&options, &code, &ptr, errorcodeptr, &branchfirstchar, + &branchreqchar, &bc, cond_depth, cd, + (lengthptr == NULL)? NULL : &length)) + { + *ptrptr = ptr; + return FALSE; + } + + /* Keep the highest bracket count in case (?| was used and some branch + has fewer than the rest. */ + + if (cd->bracount > max_bracount) max_bracount = cd->bracount; + + /* In the real compile phase, there is some post-processing to be done. */ + + if (lengthptr == NULL) + { + /* If this is the first branch, the firstchar and reqchar values for the + branch become the values for the regex. */ + + if (*last_branch != OP_ALT) + { + firstchar = branchfirstchar; + reqchar = branchreqchar; + } + + /* If this is not the first branch, the first char and reqchar have to + match the values from all the previous branches, except that if the + previous value for reqchar didn't have REQ_VARY set, it can still match, + and we set REQ_VARY for the regex. */ + + else + { + /* If we previously had a firstchar, but it doesn't match the new branch, + we have to abandon the firstchar for the regex, but if there was + previously no reqchar, it takes on the value of the old firstchar. */ + + if (firstchar >= 0 && firstchar != branchfirstchar) + { + if (reqchar < 0) reqchar = firstchar; + firstchar = REQ_NONE; + } + + /* If we (now or from before) have no firstchar, a firstchar from the + branch becomes a reqchar if there isn't a branch reqchar. */ + + if (firstchar < 0 && branchfirstchar >= 0 && branchreqchar < 0) + branchreqchar = branchfirstchar; + + /* Now ensure that the reqchars match */ + + if ((reqchar & ~REQ_VARY) != (branchreqchar & ~REQ_VARY)) + reqchar = REQ_NONE; + else reqchar |= branchreqchar; /* To "or" REQ_VARY */ + } + + /* If lookbehind, check that this branch matches a fixed-length string, and + put the length into the OP_REVERSE item. Temporarily mark the end of the + branch with OP_END. If the branch contains OP_RECURSE, the result is -3 + because there may be forward references that we can't check here. Set a + flag to cause another lookbehind check at the end. Why not do it all at the + end? Because common, erroneous checks are picked up here and the offset of + the problem can be shown. */ + + if (lookbehind) + { + int fixed_length; + *code = OP_END; + fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0, + FALSE, cd); + DPRINTF(("fixed length = %d\n", fixed_length)); + if (fixed_length == -3) + { + cd->check_lookbehind = TRUE; + } + else if (fixed_length < 0) + { + *errorcodeptr = (fixed_length == -2)? ERR36 : + (fixed_length == -4)? ERR70: ERR25; + *ptrptr = ptr; + return FALSE; + } + else { PUT(reverse_count, 0, fixed_length); } + } + } + + /* Reached end of expression, either ')' or end of pattern. In the real + compile phase, go back through the alternative branches and reverse the chain + of offsets, with the field in the BRA item now becoming an offset to the + first alternative. If there are no alternatives, it points to the end of the + group. The length in the terminating ket is always the length of the whole + bracketed item. Return leaving the pointer at the terminating char. */ + + if (*ptr != CHAR_VERTICAL_LINE) + { + if (lengthptr == NULL) + { + int branch_length = (int)(code - last_branch); + do + { + int prev_length = GET(last_branch, 1); + PUT(last_branch, 1, branch_length); + branch_length = prev_length; + last_branch -= branch_length; + } + while (branch_length > 0); + } + + /* Fill in the ket */ + + *code = OP_KET; + PUT(code, 1, (int)(code - start_bracket)); + code += 1 + LINK_SIZE; + + /* If it was a capturing subpattern, check to see if it contained any + recursive back references. If so, we must wrap it in atomic brackets. + In any event, remove the block from the chain. */ + + if (capnumber > 0) + { + if (cd->open_caps->flag) + { + memmove(start_bracket + 1 + LINK_SIZE, start_bracket, + IN_UCHARS(code - start_bracket)); + *start_bracket = OP_ONCE; + code += 1 + LINK_SIZE; + PUT(start_bracket, 1, (int)(code - start_bracket)); + *code = OP_KET; + PUT(code, 1, (int)(code - start_bracket)); + code += 1 + LINK_SIZE; + length += 2 + 2*LINK_SIZE; + } + cd->open_caps = cd->open_caps->next; + } + + /* Retain the highest bracket number, in case resetting was used. */ + + cd->bracount = max_bracount; + + /* Set values to pass back */ + + *codeptr = code; + *ptrptr = ptr; + *firstcharptr = firstchar; + *reqcharptr = reqchar; + if (lengthptr != NULL) + { + if (OFLOW_MAX - *lengthptr < length) + { + *errorcodeptr = ERR20; + return FALSE; + } + *lengthptr += length; + } + return TRUE; + } + + /* Another branch follows. In the pre-compile phase, we can move the code + pointer back to where it was for the start of the first branch. (That is, + pretend that each branch is the only one.) + + In the real compile phase, insert an ALT node. Its length field points back + to the previous branch while the bracket remains open. At the end the chain + is reversed. It's done like this so that the start of the bracket has a + zero offset until it is closed, making it possible to detect recursion. */ + + if (lengthptr != NULL) + { + code = *codeptr + 1 + LINK_SIZE + skipbytes; + length += 1 + LINK_SIZE; + } + else + { + *code = OP_ALT; + PUT(code, 1, (int)(code - last_branch)); + bc.current_branch = last_branch = code; + code += 1 + LINK_SIZE; + } + + ptr++; + } +/* Control never reaches here */ +} + + + + +/************************************************* +* Check for anchored expression * +*************************************************/ + +/* Try to find out if this is an anchored regular expression. Consider each +alternative branch. If they all start with OP_SOD or OP_CIRC, or with a bracket +all of whose alternatives start with OP_SOD or OP_CIRC (recurse ad lib), then +it's anchored. However, if this is a multiline pattern, then only OP_SOD will +be found, because ^ generates OP_CIRCM in that mode. + +We can also consider a regex to be anchored if OP_SOM starts all its branches. +This is the code for \G, which means "match at start of match position, taking +into account the match offset". + +A branch is also implicitly anchored if it starts with .* and DOTALL is set, +because that will try the rest of the pattern at all possible matching points, +so there is no point trying again.... er .... + +.... except when the .* appears inside capturing parentheses, and there is a +subsequent back reference to those parentheses. We haven't enough information +to catch that case precisely. + +At first, the best we could do was to detect when .* was in capturing brackets +and the highest back reference was greater than or equal to that level. +However, by keeping a bitmap of the first 31 back references, we can catch some +of the more common cases more precisely. + +Arguments: + code points to start of expression (the bracket) + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_anchored(register const pcre_uchar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const pcre_uchar *scode = first_significant_code( + code + PRIV(OP_lengths)[*code], FALSE); + register int op = *scode; + + /* Non-capturing brackets */ + + if (op == OP_BRA || op == OP_BRAPOS || + op == OP_SBRA || op == OP_SBRAPOS) + { + if (!is_anchored(scode, bracket_map, backref_map)) return FALSE; + } + + /* Capturing brackets */ + + else if (op == OP_CBRA || op == OP_CBRAPOS || + op == OP_SCBRA || op == OP_SCBRAPOS) + { + int n = GET2(scode, 1+LINK_SIZE); + int new_map = bracket_map | ((n < 32)? (1 << n) : 1); + if (!is_anchored(scode, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC || + op == OP_COND) + { + if (!is_anchored(scode, bracket_map, backref_map)) return FALSE; + } + + /* .* is not anchored unless DOTALL is set (which generates OP_ALLANY) and + it isn't in brackets that are or may be referenced. */ + + else if ((op == OP_TYPESTAR || op == OP_TYPEMINSTAR || + op == OP_TYPEPOSSTAR)) + { + if (scode[1] != OP_ALLANY || (bracket_map & backref_map) != 0) + return FALSE; + } + + /* Check for explicit anchoring */ + + else if (op != OP_SOD && op != OP_SOM && op != OP_CIRC) return FALSE; + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for starting with ^ or .* * +*************************************************/ + +/* This is called to find out if every branch starts with ^ or .* so that +"first char" processing can be done to speed things up in multiline +matching and for non-DOTALL patterns that start with .* (which must start at +the beginning or after \n). As in the case of is_anchored() (see above), we +have to take account of back references to capturing brackets that contain .* +because in that case we can't make the assumption. + +Arguments: + code points to start of expression (the bracket) + bracket_map a bitmap of which brackets we are inside while testing; this + handles up to substring 31; after that we just have to take + the less precise approach + backref_map the back reference bitmap + +Returns: TRUE or FALSE +*/ + +static BOOL +is_startline(const pcre_uchar *code, unsigned int bracket_map, + unsigned int backref_map) +{ +do { + const pcre_uchar *scode = first_significant_code( + code + PRIV(OP_lengths)[*code], FALSE); + register int op = *scode; + + /* If we are at the start of a conditional assertion group, *both* the + conditional assertion *and* what follows the condition must satisfy the test + for start of line. Other kinds of condition fail. Note that there may be an + auto-callout at the start of a condition. */ + + if (op == OP_COND) + { + scode += 1 + LINK_SIZE; + if (*scode == OP_CALLOUT) scode += PRIV(OP_lengths)[OP_CALLOUT]; + switch (*scode) + { + case OP_CREF: + case OP_NCREF: + case OP_RREF: + case OP_NRREF: + case OP_DEF: + return FALSE; + + default: /* Assertion */ + if (!is_startline(scode, bracket_map, backref_map)) return FALSE; + do scode += GET(scode, 1); while (*scode == OP_ALT); + scode += 1 + LINK_SIZE; + break; + } + scode = first_significant_code(scode, FALSE); + op = *scode; + } + + /* Non-capturing brackets */ + + if (op == OP_BRA || op == OP_BRAPOS || + op == OP_SBRA || op == OP_SBRAPOS) + { + if (!is_startline(scode, bracket_map, backref_map)) return FALSE; + } + + /* Capturing brackets */ + + else if (op == OP_CBRA || op == OP_CBRAPOS || + op == OP_SCBRA || op == OP_SCBRAPOS) + { + int n = GET2(scode, 1+LINK_SIZE); + int new_map = bracket_map | ((n < 32)? (1 << n) : 1); + if (!is_startline(scode, new_map, backref_map)) return FALSE; + } + + /* Other brackets */ + + else if (op == OP_ASSERT || op == OP_ONCE || op == OP_ONCE_NC) + { + if (!is_startline(scode, bracket_map, backref_map)) return FALSE; + } + + /* .* means "start at start or after \n" if it isn't in brackets that + may be referenced. */ + + else if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR || op == OP_TYPEPOSSTAR) + { + if (scode[1] != OP_ANY || (bracket_map & backref_map) != 0) return FALSE; + } + + /* Check for explicit circumflex */ + + else if (op != OP_CIRC && op != OP_CIRCM) return FALSE; + + /* Move on to the next alternative */ + + code += GET(code, 1); + } +while (*code == OP_ALT); /* Loop for each alternative */ +return TRUE; +} + + + +/************************************************* +* Check for asserted fixed first char * +*************************************************/ + +/* During compilation, the "first char" settings from forward assertions are +discarded, because they can cause conflicts with actual literals that follow. +However, if we end up without a first char setting for an unanchored pattern, +it is worth scanning the regex to see if there is an initial asserted first +char. If all branches start with the same asserted char, or with a bracket all +of whose alternatives start with the same asserted char (recurse ad lib), then +we return that char, otherwise -1. + +Arguments: + code points to start of expression (the bracket) + inassert TRUE if in an assertion + +Returns: -1 or the fixed first char +*/ + +static int +find_firstassertedchar(const pcre_uchar *code, BOOL inassert) +{ +register int c = -1; +do { + int d; + int xl = (*code == OP_CBRA || *code == OP_SCBRA || + *code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0; + const pcre_uchar *scode = first_significant_code(code + 1+LINK_SIZE + xl, + TRUE); + register int op = *scode; + + switch(op) + { + default: + return -1; + + case OP_BRA: + case OP_BRAPOS: + case OP_CBRA: + case OP_SCBRA: + case OP_CBRAPOS: + case OP_SCBRAPOS: + case OP_ASSERT: + case OP_ONCE: + case OP_ONCE_NC: + case OP_COND: + if ((d = find_firstassertedchar(scode, op == OP_ASSERT)) < 0) + return -1; + if (c < 0) c = d; else if (c != d) return -1; + break; + + case OP_EXACT: + scode += IMM2_SIZE; + /* Fall through */ + + case OP_CHAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + if (!inassert) return -1; + if (c < 0) c = scode[1]; + else if (c != scode[1]) return -1; + break; + + case OP_EXACTI: + scode += IMM2_SIZE; + /* Fall through */ + + case OP_CHARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_POSPLUSI: + if (!inassert) return -1; + if (c < 0) c = scode[1] | REQ_CASELESS; + else if (c != scode[1]) return -1; + break; + } + + code += GET(code, 1); + } +while (*code == OP_ALT); +return c; +} + + + +/************************************************* +* Compile a Regular Expression * +*************************************************/ + +/* This function takes a string and returns a pointer to a block of store +holding a compiled version of the expression. The original API for this +function had no error code return variable; it is retained for backwards +compatibility. The new function is given a new name. + +Arguments: + pattern the regular expression + options various option bits + errorcodeptr pointer to error code variable (pcre_compile2() only) + can be NULL if you don't want a code value + errorptr pointer to pointer to error text + erroroffset ptr offset in pattern where error was detected + tables pointer to character tables or NULL + +Returns: pointer to compiled data block, or NULL on error, + with errorptr and erroroffset set +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION +pcre_compile(const char *pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +#else +PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION +pcre16_compile(PCRE_SPTR16 pattern, int options, const char **errorptr, + int *erroroffset, const unsigned char *tables) +#endif +{ +#ifdef COMPILE_PCRE8 +return pcre_compile2(pattern, options, NULL, errorptr, erroroffset, tables); +#else +return pcre16_compile2(pattern, options, NULL, errorptr, erroroffset, tables); +#endif +} + + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN pcre * PCRE_CALL_CONVENTION +pcre_compile2(const char *pattern, int options, int *errorcodeptr, + const char **errorptr, int *erroroffset, const unsigned char *tables) +#else +PCRE_EXP_DEFN pcre16 * PCRE_CALL_CONVENTION +pcre16_compile2(PCRE_SPTR16 pattern, int options, int *errorcodeptr, + const char **errorptr, int *erroroffset, const unsigned char *tables) +#endif +{ +REAL_PCRE *re; +int length = 1; /* For final END opcode */ +pcre_int32 firstchar, reqchar; +int newline; +int errorcode = 0; +int skipatstart = 0; +BOOL utf; +size_t size; +pcre_uchar *code; +const pcre_uchar *codestart; +const pcre_uchar *ptr; +compile_data compile_block; +compile_data *cd = &compile_block; + +/* This space is used for "compiling" into during the first phase, when we are +computing the amount of memory that is needed. Compiled items are thrown away +as soon as possible, so that a fairly large buffer should be sufficient for +this purpose. The same space is used in the second phase for remembering where +to fill in forward references to subpatterns. That may overflow, in which case +new memory is obtained from malloc(). */ + +pcre_uchar cworkspace[COMPILE_WORK_SIZE]; + +/* Set this early so that early errors get offset 0. */ + +ptr = (const pcre_uchar *)pattern; + +/* We can't pass back an error message if errorptr is NULL; I guess the best we +can do is just return NULL, but we can set a code value if there is a code +pointer. */ + +if (errorptr == NULL) + { + if (errorcodeptr != NULL) *errorcodeptr = 99; + return NULL; + } + +*errorptr = NULL; +if (errorcodeptr != NULL) *errorcodeptr = ERR0; + +/* However, we can give a message for this error */ + +if (erroroffset == NULL) + { + errorcode = ERR16; + goto PCRE_EARLY_ERROR_RETURN2; + } + +*erroroffset = 0; + +/* Set up pointers to the individual character tables */ + +if (tables == NULL) tables = PRIV(default_tables); +cd->lcc = tables + lcc_offset; +cd->fcc = tables + fcc_offset; +cd->cbits = tables + cbits_offset; +cd->ctypes = tables + ctypes_offset; + +/* Check that all undefined public option bits are zero */ + +if ((options & ~PUBLIC_COMPILE_OPTIONS) != 0) + { + errorcode = ERR17; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Check for global one-time settings at the start of the pattern, and remember +the offset for later. */ + +while (ptr[skipatstart] == CHAR_LEFT_PARENTHESIS && + ptr[skipatstart+1] == CHAR_ASTERISK) + { + int newnl = 0; + int newbsr = 0; + +#ifdef COMPILE_PCRE8 + if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 5) == 0) + { skipatstart += 7; options |= PCRE_UTF8; continue; } +#endif +#ifdef COMPILE_PCRE16 + if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UTF_RIGHTPAR, 6) == 0) + { skipatstart += 8; options |= PCRE_UTF16; continue; } +#endif + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_UCP_RIGHTPAR, 4) == 0) + { skipatstart += 6; options |= PCRE_UCP; continue; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_NO_START_OPT_RIGHTPAR, 13) == 0) + { skipatstart += 15; options |= PCRE_NO_START_OPTIMIZE; continue; } + + if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CR_RIGHTPAR, 3) == 0) + { skipatstart += 5; newnl = PCRE_NEWLINE_CR; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_LF_RIGHTPAR, 3) == 0) + { skipatstart += 5; newnl = PCRE_NEWLINE_LF; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_CRLF_RIGHTPAR, 5) == 0) + { skipatstart += 7; newnl = PCRE_NEWLINE_CR + PCRE_NEWLINE_LF; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANY_RIGHTPAR, 4) == 0) + { skipatstart += 6; newnl = PCRE_NEWLINE_ANY; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_ANYCRLF_RIGHTPAR, 8) == 0) + { skipatstart += 10; newnl = PCRE_NEWLINE_ANYCRLF; } + + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_ANYCRLF_RIGHTPAR, 12) == 0) + { skipatstart += 14; newbsr = PCRE_BSR_ANYCRLF; } + else if (STRNCMP_UC_C8(ptr+skipatstart+2, STRING_BSR_UNICODE_RIGHTPAR, 12) == 0) + { skipatstart += 14; newbsr = PCRE_BSR_UNICODE; } + + if (newnl != 0) + options = (options & ~PCRE_NEWLINE_BITS) | newnl; + else if (newbsr != 0) + options = (options & ~(PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) | newbsr; + else break; + } + +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +utf = (options & PCRE_UTF8) != 0; + +/* Can't support UTF unless PCRE has been compiled to include the code. The +return of an error code from PRIV(valid_utf)() is a new feature, introduced in +release 8.13. It is passed back from pcre_[dfa_]exec(), but at the moment is +not used here. */ + +#ifdef SUPPORT_UTF +if (utf && (options & PCRE_NO_UTF8_CHECK) == 0 && + (errorcode = PRIV(valid_utf)((PCRE_PUCHAR)pattern, -1, erroroffset)) != 0) + { +#ifdef COMPILE_PCRE8 + errorcode = ERR44; +#else + errorcode = ERR74; +#endif + goto PCRE_EARLY_ERROR_RETURN2; + } +#else +if (utf) + { + errorcode = ERR32; + goto PCRE_EARLY_ERROR_RETURN; + } +#endif + +/* Can't support UCP unless PCRE has been compiled to include the code. */ + +#ifndef SUPPORT_UCP +if ((options & PCRE_UCP) != 0) + { + errorcode = ERR67; + goto PCRE_EARLY_ERROR_RETURN; + } +#endif + +/* Check validity of \R options. */ + +if ((options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == + (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) + { + errorcode = ERR56; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Handle different types of newline. The three bits give seven cases. The +current code allows for fixed one- or two-byte sequences, plus "any" and +"anycrlf". */ + +switch (options & PCRE_NEWLINE_BITS) + { + case 0: newline = NEWLINE; break; /* Build-time default */ + case PCRE_NEWLINE_CR: newline = CHAR_CR; break; + case PCRE_NEWLINE_LF: newline = CHAR_NL; break; + case PCRE_NEWLINE_CR+ + PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; + case PCRE_NEWLINE_ANY: newline = -1; break; + case PCRE_NEWLINE_ANYCRLF: newline = -2; break; + default: errorcode = ERR56; goto PCRE_EARLY_ERROR_RETURN; + } + +if (newline == -2) + { + cd->nltype = NLTYPE_ANYCRLF; + } +else if (newline < 0) + { + cd->nltype = NLTYPE_ANY; + } +else + { + cd->nltype = NLTYPE_FIXED; + if (newline > 255) + { + cd->nllen = 2; + cd->nl[0] = (newline >> 8) & 255; + cd->nl[1] = newline & 255; + } + else + { + cd->nllen = 1; + cd->nl[0] = newline; + } + } + +/* Maximum back reference and backref bitmap. The bitmap records up to 31 back +references to help in deciding whether (.*) can be treated as anchored or not. +*/ + +cd->top_backref = 0; +cd->backref_map = 0; + +/* Reflect pattern for debugging output */ + +DPRINTF(("------------------------------------------------------------------\n")); +#ifdef PCRE_DEBUG +print_puchar(stdout, (PCRE_PUCHAR)pattern); +#endif +DPRINTF(("\n")); + +/* Pretend to compile the pattern while actually just accumulating the length +of memory required. This behaviour is triggered by passing a non-NULL final +argument to compile_regex(). We pass a block of workspace (cworkspace) for it +to compile parts of the pattern into; the compiled code is discarded when it is +no longer needed, so hopefully this workspace will never overflow, though there +is a test for its doing so. */ + +cd->bracount = cd->final_bracount = 0; +cd->names_found = 0; +cd->name_entry_size = 0; +cd->name_table = NULL; +cd->start_code = cworkspace; +cd->hwm = cworkspace; +cd->start_workspace = cworkspace; +cd->workspace_size = COMPILE_WORK_SIZE; +cd->start_pattern = (const pcre_uchar *)pattern; +cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern)); +cd->req_varyopt = 0; +cd->assert_depth = 0; +cd->external_options = options; +cd->external_flags = 0; +cd->open_caps = NULL; + +/* Now do the pre-compile. On error, errorcode will be set non-zero, so we +don't need to look at the result of the function here. The initial options have +been put into the cd block so that they can be changed if an option setting is +found within the regex right at the beginning. Bringing initial option settings +outside can help speed up starting point checks. */ + +ptr += skipatstart; +code = cworkspace; +*code = OP_BRA; +(void)compile_regex(cd->external_options, &code, &ptr, &errorcode, FALSE, + FALSE, 0, 0, &firstchar, &reqchar, NULL, cd, &length); +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; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Compute the size of data block needed and get it, either from malloc or +externally provided function. Integer overflow should no longer be possible +because nowadays we limit the maximum value of cd->names_found and +cd->name_entry_size. */ + +size = sizeof(REAL_PCRE) + (length + cd->names_found * cd->name_entry_size) * sizeof(pcre_uchar); +re = (REAL_PCRE *)(PUBL(malloc))(size); + +if (re == NULL) + { + errorcode = ERR21; + goto PCRE_EARLY_ERROR_RETURN; + } + +/* Put in the magic number, and save the sizes, initial options, internal +flags, and character table pointer. NULL is used for the default character +tables. The nullpad field is at the end; it's there to help in the case when a +regex compiled on a system with 4-byte pointers is run on another with 8-byte +pointers. */ + +re->magic_number = MAGIC_NUMBER; +re->size = (int)size; +re->options = cd->external_options; +re->flags = cd->external_flags; +re->dummy1 = 0; +re->first_char = 0; +re->req_char = 0; +re->name_table_offset = sizeof(REAL_PCRE) / sizeof(pcre_uchar); +re->name_entry_size = cd->name_entry_size; +re->name_count = cd->names_found; +re->ref_count = 0; +re->tables = (tables == PRIV(default_tables))? NULL : tables; +re->nullpad = NULL; + +/* The starting points of the name/number translation table and of the code are +passed around in the compile data block. The start/end pattern and initial +options are already set from the pre-compile phase, as is the name_entry_size +field. Reset the bracket count and the names_found field. Also reset the hwm +field; this time it's used for remembering forward references to subpatterns. +*/ + +cd->final_bracount = cd->bracount; /* Save for checking forward references */ +cd->assert_depth = 0; +cd->bracount = 0; +cd->names_found = 0; +cd->name_table = (pcre_uchar *)re + re->name_table_offset; +codestart = cd->name_table + re->name_entry_size * re->name_count; +cd->start_code = codestart; +cd->hwm = (pcre_uchar *)(cd->start_workspace); +cd->req_varyopt = 0; +cd->had_accept = FALSE; +cd->check_lookbehind = FALSE; +cd->open_caps = NULL; + +/* Set up a starting, non-extracting bracket, then compile the expression. On +error, errorcode will be set non-zero, so we don't need to look at the result +of the function here. */ + +ptr = (const pcre_uchar *)pattern + skipatstart; +code = (pcre_uchar *)codestart; +*code = OP_BRA; +(void)compile_regex(re->options, &code, &ptr, &errorcode, FALSE, FALSE, 0, 0, + &firstchar, &reqchar, NULL, cd, NULL); +re->top_bracket = cd->bracount; +re->top_backref = cd->top_backref; +re->flags = cd->external_flags | PCRE_MODE; + +if (cd->had_accept) reqchar = REQ_NONE; /* Must disable after (*ACCEPT) */ + +/* If not reached end of pattern on success, there's an excess bracket. */ + +if (errorcode == 0 && *ptr != 0) errorcode = ERR22; + +/* Fill in the terminating state and check for disastrous overflow, but +if debugging, leave the test till after things are printed out. */ + +*code++ = OP_END; + +#ifndef PCRE_DEBUG +if (code - codestart > length) errorcode = ERR23; +#endif + +/* Fill in any forward references that are required. There may be repeated +references; optimize for them, as searching a large regex takes time. */ + +if (cd->hwm > cd->start_workspace) + { + int prev_recno = -1; + const pcre_uchar *groupptr = NULL; + while (errorcode == 0 && cd->hwm > cd->start_workspace) + { + int offset, recno; + cd->hwm -= LINK_SIZE; + offset = GET(cd->hwm, 0); + recno = GET(codestart, offset); + if (recno != prev_recno) + { + groupptr = PRIV(find_bracket)(codestart, utf, recno); + prev_recno = recno; + } + if (groupptr == NULL) errorcode = ERR53; + else PUT(((pcre_uchar *)codestart), offset, (int)(groupptr - codestart)); + } + } + +/* If the workspace had to be expanded, free the new memory. */ + +if (cd->workspace_size > COMPILE_WORK_SIZE) + (PUBL(free))((void *)cd->start_workspace); + +/* Give an error if there's back reference to a non-existent capturing +subpattern. */ + +if (errorcode == 0 && re->top_backref > re->top_bracket) errorcode = ERR15; + +/* If there were any lookbehind assertions that contained OP_RECURSE +(recursions or subroutine calls), a flag is set for them to be checked here, +because they may contain forward references. Actual recursions can't be fixed +length, but subroutine calls can. It is done like this so that those without +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) + { + pcre_uchar *cc = (pcre_uchar *)codestart; + + /* Loop, searching for OP_REVERSE items, and process those that do not have + their length set. (Actually, it will also re-process any that have a length + of zero, but that is a pathological case, and it does no harm.) When we find + one, we temporarily terminate the branch it is in while we scan it. */ + + for (cc = (pcre_uchar *)PRIV(find_bracket)(codestart, utf, -1); + cc != NULL; + cc = (pcre_uchar *)PRIV(find_bracket)(cc, utf, -1)) + { + if (GET(cc, 1) == 0) + { + int fixed_length; + pcre_uchar *be = cc - 1 - LINK_SIZE + GET(cc, -LINK_SIZE); + int end_op = *be; + *be = OP_END; + fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE, + cd); + *be = end_op; + DPRINTF(("fixed length = %d\n", fixed_length)); + if (fixed_length < 0) + { + errorcode = (fixed_length == -2)? ERR36 : + (fixed_length == -4)? ERR70 : ERR25; + break; + } + PUT(cc, 1, fixed_length); + } + cc += 1 + LINK_SIZE; + } + } + +/* Failed to compile, or error while post-processing */ + +if (errorcode != 0) + { + (PUBL(free))(re); + PCRE_EARLY_ERROR_RETURN: + *erroroffset = (int)(ptr - (const pcre_uchar *)pattern); + PCRE_EARLY_ERROR_RETURN2: + *errorptr = find_error_text(errorcode); + if (errorcodeptr != NULL) *errorcodeptr = errorcode; + return NULL; + } + +/* If the anchored option was not passed, set the flag if we can determine that +the pattern is anchored by virtue of ^ characters or \A or anything else (such +as starting with .* when DOTALL is set). + +Otherwise, if we know what the first byte has to be, save it, because that +speeds up unanchored matches no end. If not, see if we can set the +PCRE_STARTLINE flag. This is helpful for multiline matches when all branches +start with ^. and also when all branches start with .* for non-DOTALL matches. +*/ + +if ((re->options & PCRE_ANCHORED) == 0) + { + if (is_anchored(codestart, 0, cd->backref_map)) + re->options |= PCRE_ANCHORED; + else + { + if (firstchar < 0) + firstchar = find_firstassertedchar(codestart, FALSE); + if (firstchar >= 0) /* Remove caseless flag for non-caseable chars */ + { +#ifdef COMPILE_PCRE8 + re->first_char = firstchar & 0xff; +#else +#ifdef COMPILE_PCRE16 + re->first_char = firstchar & 0xffff; +#endif +#endif + if ((firstchar & REQ_CASELESS) != 0) + { +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + /* We ignore non-ASCII first chars in 8 bit mode. */ + if (utf) + { + if (re->first_char < 128) + { + if (cd->fcc[re->first_char] != re->first_char) + re->flags |= PCRE_FCH_CASELESS; + } + else if (UCD_OTHERCASE(re->first_char) != re->first_char) + re->flags |= PCRE_FCH_CASELESS; + } + else +#endif + if (MAX_255(re->first_char) + && cd->fcc[re->first_char] != re->first_char) + re->flags |= PCRE_FCH_CASELESS; + } + + re->flags |= PCRE_FIRSTSET; + } + else if (is_startline(codestart, 0, cd->backref_map)) + re->flags |= PCRE_STARTLINE; + } + } + +/* For an anchored pattern, we use the "required byte" only if it follows a +variable length item in the regex. Remove the caseless flag for non-caseable +bytes. */ + +if (reqchar >= 0 && + ((re->options & PCRE_ANCHORED) == 0 || (reqchar & REQ_VARY) != 0)) + { +#ifdef COMPILE_PCRE8 + re->req_char = reqchar & 0xff; +#else +#ifdef COMPILE_PCRE16 + re->req_char = reqchar & 0xffff; +#endif +#endif + if ((reqchar & REQ_CASELESS) != 0) + { +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + /* We ignore non-ASCII first chars in 8 bit mode. */ + if (utf) + { + if (re->req_char < 128) + { + if (cd->fcc[re->req_char] != re->req_char) + re->flags |= PCRE_RCH_CASELESS; + } + else if (UCD_OTHERCASE(re->req_char) != re->req_char) + re->flags |= PCRE_RCH_CASELESS; + } + else +#endif + if (MAX_255(re->req_char) && cd->fcc[re->req_char] != re->req_char) + re->flags |= PCRE_RCH_CASELESS; + } + + re->flags |= PCRE_REQCHSET; + } + +/* Print out the compiled data if debugging is enabled. This is never the +case when building a production library. */ + +#ifdef PCRE_DEBUG +printf("Length = %d top_bracket = %d top_backref = %d\n", + length, re->top_bracket, re->top_backref); + +printf("Options=%08x\n", re->options); + +if ((re->flags & PCRE_FIRSTSET) != 0) + { + pcre_uchar ch = re->first_char; + const char *caseless = + ((re->flags & PCRE_FCH_CASELESS) == 0)? "" : " (caseless)"; + if (PRINTABLE(ch)) printf("First char = %c%s\n", ch, caseless); + else printf("First char = \\x%02x%s\n", ch, caseless); + } + +if ((re->flags & PCRE_REQCHSET) != 0) + { + pcre_uchar ch = re->req_char; + const char *caseless = + ((re->flags & PCRE_RCH_CASELESS) == 0)? "" : " (caseless)"; + if (PRINTABLE(ch)) printf("Req char = %c%s\n", ch, caseless); + else printf("Req char = \\x%02x%s\n", ch, caseless); + } + +#ifdef COMPILE_PCRE8 +pcre_printint((pcre *)re, stdout, TRUE); +#else +pcre16_printint((pcre *)re, stdout, TRUE); +#endif + +/* This check is done here in the debugging case so that the code that +was compiled can be seen. */ + +if (code - codestart > length) + { + (PUBL(free))(re); + *errorptr = find_error_text(ERR23); + *erroroffset = ptr - (pcre_uchar *)pattern; + if (errorcodeptr != NULL) *errorcodeptr = ERR23; + return NULL; + } +#endif /* PCRE_DEBUG */ + +#ifdef COMPILE_PCRE8 +return (pcre *)re; +#else +return (pcre16 *)re; +#endif +} + +/* End of pcre_compile.c */ diff --git a/src/3rdparty/pcre/pcre_config.c b/src/3rdparty/pcre/pcre_config.c new file mode 100644 index 0000000000..6ebafaf06a --- /dev/null +++ b/src/3rdparty/pcre/pcre_config.c @@ -0,0 +1,170 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_config(). */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +/* Keep the original link size. */ +static int real_link_size = LINK_SIZE; + +#include "pcre_internal.h" + + +/************************************************* +* Return info about what features are configured * +*************************************************/ + +/* This function has an extensible interface so that additional items can be +added compatibly. + +Arguments: + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_config(int what, void *where) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_config(int what, void *where) +#endif +{ +switch (what) + { + case PCRE_CONFIG_UTF8: +#if defined COMPILE_PCRE16 + *((int *)where) = 0; + return PCRE_ERROR_BADOPTION; +#else +#if defined SUPPORT_UTF + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; +#endif + + case PCRE_CONFIG_UTF16: +#if defined COMPILE_PCRE8 + *((int *)where) = 0; + return PCRE_ERROR_BADOPTION; +#else +#if defined SUPPORT_UTF + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; +#endif + + case PCRE_CONFIG_UNICODE_PROPERTIES: +#ifdef SUPPORT_UCP + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_JIT: +#ifdef SUPPORT_JIT + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_JITTARGET: +#ifdef SUPPORT_JIT + *((const char **)where) = PRIV(jit_get_target)(); +#else + *((const char **)where) = NULL; +#endif + break; + + case PCRE_CONFIG_NEWLINE: + *((int *)where) = NEWLINE; + break; + + case PCRE_CONFIG_BSR: +#ifdef BSR_ANYCRLF + *((int *)where) = 1; +#else + *((int *)where) = 0; +#endif + break; + + case PCRE_CONFIG_LINK_SIZE: + *((int *)where) = real_link_size; + break; + + case PCRE_CONFIG_POSIX_MALLOC_THRESHOLD: + *((int *)where) = POSIX_MALLOC_THRESHOLD; + break; + + case PCRE_CONFIG_MATCH_LIMIT: + *((unsigned long int *)where) = MATCH_LIMIT; + break; + + case PCRE_CONFIG_MATCH_LIMIT_RECURSION: + *((unsigned long int *)where) = MATCH_LIMIT_RECURSION; + break; + + case PCRE_CONFIG_STACKRECURSE: +#ifdef NO_RECURSE + *((int *)where) = 0; +#else + *((int *)where) = 1; +#endif + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + +/* End of pcre_config.c */ diff --git a/src/3rdparty/pcre/pcre_dfa_exec.c b/src/3rdparty/pcre/pcre_dfa_exec.c new file mode 100644 index 0000000000..bc89c0de41 --- /dev/null +++ b/src/3rdparty/pcre/pcre_dfa_exec.c @@ -0,0 +1,3490 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language (but see +below for why this module is different). + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_dfa_exec(), which is an +alternative matching function that uses a sort of DFA algorithm (not a true +FSM). This is NOT Perl- compatible, but it has advantages in certain +applications. */ + + +/* NOTE ABOUT PERFORMANCE: A user of this function sent some code that improved +the performance of his patterns greatly. I could not use it as it stood, as it +was not thread safe, and made assumptions about pattern sizes. Also, it caused +test 7 to loop, and test 9 to crash with a segfault. + +The issue is the check for duplicate states, which is done by a simple linear +search up the state list. (Grep for "duplicate" below to find the code.) For +many patterns, there will never be many states active at one time, so a simple +linear search is fine. In patterns that have many active states, it might be a +bottleneck. The suggested code used an indexing scheme to remember which states +had previously been used for each character, and avoided the linear search when +it knew there was no chance of a duplicate. This was implemented when adding +states to the state lists. + +I wrote some thread-safe, not-limited code to try something similar at the time +of checking for duplicates (instead of when adding states), using index vectors +on the stack. It did give a 13% improvement with one specially constructed +pattern for certain subject strings, but on other strings and on many of the +simpler patterns in the test suite it did worse. The major problem, I think, +was the extra time to initialize the index. This had to be done for each call +of internal_dfa_exec(). (The supplied patch used a static vector, initialized +only once - I suspect this was the cause of the problems with the tests.) + +Overall, I concluded that the gains in some cases did not outweigh the losses +in others, so I abandoned this code. */ + + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK md /* Block containing newline information */ +#define PSSTART start_subject /* Field containing processed string start */ +#define PSEND end_subject /* Field containing processed string end */ + +#include "pcre_internal.h" + + +/* For use to indent debugging output */ + +#define SP " " + + +/************************************************* +* Code parameters and static tables * +*************************************************/ + +/* These are offsets that are used to turn the OP_TYPESTAR and friends opcodes +into others, under special conditions. A gap of 20 between the blocks should be +enough. The resulting opcodes don't have to be less than 256 because they are +never stored, so we push them well clear of the normal opcodes. */ + +#define OP_PROP_EXTRA 300 +#define OP_EXTUNI_EXTRA 320 +#define OP_ANYNL_EXTRA 340 +#define OP_HSPACE_EXTRA 360 +#define OP_VSPACE_EXTRA 380 + + +/* This table identifies those opcodes that are followed immediately by a +character that is to be tested in some way. This makes it possible to +centralize the loading of these characters. In the case of Type * etc, the +"character" is the opcode for \D, \d, \S, \s, \W, or \w, which will always be a +small value. Non-zero values in the table are the offsets from the opcode where +the character is to be found. ***NOTE*** If the start of this table is +modified, the three tables that follow must also be modified. */ + +static const pcre_uint8 coptable[] = { + 0, /* End */ + 0, 0, 0, 0, 0, /* \A, \G, \K, \B, \b */ + 0, 0, 0, 0, 0, 0, /* \D, \d, \S, \s, \W, \w */ + 0, 0, 0, /* Any, AllAny, Anybyte */ + 0, 0, /* \P, \p */ + 0, 0, 0, 0, 0, /* \R, \H, \h, \V, \v */ + 0, /* \X */ + 0, 0, 0, 0, 0, 0, /* \Z, \z, ^, ^M, $, $M */ + 1, /* Char */ + 1, /* Chari */ + 1, /* not */ + 1, /* noti */ + /* Positive single-char repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto, minupto */ + 1+IMM2_SIZE, /* exact */ + 1, 1, 1, 1+IMM2_SIZE, /* *+, ++, ?+, upto+ */ + 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* upto I, minupto I */ + 1+IMM2_SIZE, /* exact I */ + 1, 1, 1, 1+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ + /* Negative single-char repeats - only for chars < 256 */ + 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto, minupto */ + 1+IMM2_SIZE, /* NOT exact */ + 1, 1, 1, 1+IMM2_SIZE, /* NOT *+, ++, ?+, upto+ */ + 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* NOT upto I, minupto I */ + 1+IMM2_SIZE, /* NOT exact I */ + 1, 1, 1, 1+IMM2_SIZE, /* NOT *+I, ++I, ?+I, upto+I */ + /* Positive type repeats */ + 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* Type upto, minupto */ + 1+IMM2_SIZE, /* Type exact */ + 1, 1, 1, 1+IMM2_SIZE, /* Type *+, ++, ?+, upto+ */ + /* Character class & ref repeats */ + 0, 0, 0, 0, 0, 0, /* *, *?, +, +?, ?, ?? */ + 0, 0, /* CRRANGE, CRMINRANGE */ + 0, /* CLASS */ + 0, /* NCLASS */ + 0, /* XCLASS - variable length */ + 0, /* REF */ + 0, /* REFI */ + 0, /* RECURSE */ + 0, /* CALLOUT */ + 0, /* Alt */ + 0, /* Ket */ + 0, /* KetRmax */ + 0, /* KetRmin */ + 0, /* KetRpos */ + 0, /* Reverse */ + 0, /* Assert */ + 0, /* Assert not */ + 0, /* Assert behind */ + 0, /* Assert behind not */ + 0, 0, /* ONCE, ONCE_NC */ + 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ + 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ + 0, 0, /* CREF, NCREF */ + 0, 0, /* RREF, NRREF */ + 0, /* DEF */ + 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ + 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ + 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ + 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ + 0, 0 /* CLOSE, SKIPZERO */ +}; + +/* This table identifies those opcodes that inspect a character. It is used to +remember the fact that a character could have been inspected when the end of +the subject is reached. ***NOTE*** If the start of this table is modified, the +two tables that follow must also be modified. */ + +static const pcre_uint8 poptable[] = { + 0, /* End */ + 0, 0, 0, 1, 1, /* \A, \G, \K, \B, \b */ + 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ + 1, 1, 1, /* Any, AllAny, Anybyte */ + 1, 1, /* \P, \p */ + 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ + 1, /* \X */ + 0, 0, 0, 0, 0, 0, /* \Z, \z, ^, ^M, $, $M */ + 1, /* Char */ + 1, /* Chari */ + 1, /* not */ + 1, /* noti */ + /* Positive single-char repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 1, 1, 1, /* upto, minupto, exact */ + 1, 1, 1, 1, /* *+, ++, ?+, upto+ */ + 1, 1, 1, 1, 1, 1, /* *I, *?I, +I, +?I, ?I, ??I */ + 1, 1, 1, /* upto I, minupto I, exact I */ + 1, 1, 1, 1, /* *+I, ++I, ?+I, upto+I */ + /* Negative single-char repeats - only for chars < 256 */ + 1, 1, 1, 1, 1, 1, /* NOT *, *?, +, +?, ?, ?? */ + 1, 1, 1, /* NOT upto, minupto, exact */ + 1, 1, 1, 1, /* NOT *+, ++, ?+, upto+ */ + 1, 1, 1, 1, 1, 1, /* NOT *I, *?I, +I, +?I, ?I, ??I */ + 1, 1, 1, /* NOT upto I, minupto I, exact I */ + 1, 1, 1, 1, /* NOT *+I, ++I, ?+I, upto+I */ + /* Positive type repeats */ + 1, 1, 1, 1, 1, 1, /* Type *, *?, +, +?, ?, ?? */ + 1, 1, 1, /* Type upto, minupto, exact */ + 1, 1, 1, 1, /* Type *+, ++, ?+, upto+ */ + /* Character class & ref repeats */ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ + 1, 1, /* CRRANGE, CRMINRANGE */ + 1, /* CLASS */ + 1, /* NCLASS */ + 1, /* XCLASS - variable length */ + 0, /* REF */ + 0, /* REFI */ + 0, /* RECURSE */ + 0, /* CALLOUT */ + 0, /* Alt */ + 0, /* Ket */ + 0, /* KetRmax */ + 0, /* KetRmin */ + 0, /* KetRpos */ + 0, /* Reverse */ + 0, /* Assert */ + 0, /* Assert not */ + 0, /* Assert behind */ + 0, /* Assert behind not */ + 0, 0, /* ONCE, ONCE_NC */ + 0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */ + 0, 0, 0, 0, 0, /* SBRA, SBRAPOS, SCBRA, SCBRAPOS, SCOND */ + 0, 0, /* CREF, NCREF */ + 0, 0, /* RREF, NRREF */ + 0, /* DEF */ + 0, 0, 0, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ + 0, 0, 0, /* MARK, PRUNE, PRUNE_ARG */ + 0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */ + 0, 0, 0, 0, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ + 0, 0 /* CLOSE, SKIPZERO */ +}; + +/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W, +and \w */ + +static const pcre_uint8 toptable1[] = { + 0, 0, 0, 0, 0, 0, + ctype_digit, ctype_digit, + ctype_space, ctype_space, + ctype_word, ctype_word, + 0, 0 /* OP_ANY, OP_ALLANY */ +}; + +static const pcre_uint8 toptable2[] = { + 0, 0, 0, 0, 0, 0, + ctype_digit, 0, + ctype_space, 0, + ctype_word, 0, + 1, 1 /* OP_ANY, OP_ALLANY */ +}; + + +/* Structure for holding data about a particular state, which is in effect the +current data for an active path through the match tree. It must consist +entirely of ints because the working vector we are passed, and which we put +these structures in, is a vector of ints. */ + +typedef struct stateblock { + int offset; /* Offset to opcode */ + int count; /* Count for repeats */ + int data; /* Some use extra data */ +} stateblock; + +#define INTS_PER_STATEBLOCK (sizeof(stateblock)/sizeof(int)) + + +#ifdef PCRE_DEBUG +/************************************************* +* Print character string * +*************************************************/ + +/* Character string printing function for debugging. + +Arguments: + p points to string + length number of bytes + f where to print + +Returns: nothing +*/ + +static void +pchars(const pcre_uchar *p, int length, FILE *f) +{ +int c; +while (length-- > 0) + { + if (isprint(c = *(p++))) + fprintf(f, "%c", c); + else + fprintf(f, "\\x%02x", c); + } +} +#endif + + + +/************************************************* +* Execute a Regular Expression - DFA engine * +*************************************************/ + +/* This internal function applies a compiled pattern to a subject string, +starting at a given point, using a DFA engine. This function is called from the +external one, possibly multiple times if the pattern is not anchored. The +function calls itself recursively for some kinds of subpattern. + +Arguments: + md the match_data block with fixed information + this_start_code the opening bracket of this subexpression's code + current_subject where we currently are in the subject string + start_offset start offset in the subject string + offsets vector to contain the matching string offsets + offsetcount size of same + workspace vector of workspace + wscount size of same + rlevel function call recursion level + +Returns: > 0 => number of match offset pairs placed in offsets + = 0 => offsets overflowed; longest matches are present + -1 => failed to match + < -1 => some kind of unexpected problem + +The following macros are used for adding states to the two state vectors (one +for the current character, one for the following character). */ + +#define ADD_ACTIVE(x,y) \ + if (active_count++ < wscount) \ + { \ + next_active_state->offset = (x); \ + next_active_state->count = (y); \ + next_active_state++; \ + DPRINTF(("%.*sADD_ACTIVE(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_ACTIVE_DATA(x,y,z) \ + if (active_count++ < wscount) \ + { \ + next_active_state->offset = (x); \ + next_active_state->count = (y); \ + next_active_state->data = (z); \ + next_active_state++; \ + DPRINTF(("%.*sADD_ACTIVE_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_NEW(x,y) \ + if (new_count++ < wscount) \ + { \ + next_new_state->offset = (x); \ + next_new_state->count = (y); \ + next_new_state++; \ + DPRINTF(("%.*sADD_NEW(%d,%d)\n", rlevel*2-2, SP, (x), (y))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +#define ADD_NEW_DATA(x,y,z) \ + if (new_count++ < wscount) \ + { \ + next_new_state->offset = (x); \ + next_new_state->count = (y); \ + next_new_state->data = (z); \ + next_new_state++; \ + DPRINTF(("%.*sADD_NEW_DATA(%d,%d,%d)\n", rlevel*2-2, SP, (x), (y), (z))); \ + } \ + else return PCRE_ERROR_DFA_WSSIZE + +/* And now, here is the code */ + +static int +internal_dfa_exec( + dfa_match_data *md, + const pcre_uchar *this_start_code, + const pcre_uchar *current_subject, + int start_offset, + int *offsets, + int offsetcount, + int *workspace, + int wscount, + int rlevel) +{ +stateblock *active_states, *new_states, *temp_states; +stateblock *next_active_state, *next_new_state; + +const pcre_uint8 *ctypes, *lcc, *fcc; +const pcre_uchar *ptr; +const pcre_uchar *end_code, *first_op; + +dfa_recursion_info new_recursive; + +int active_count, new_count, match_count; + +/* Some fields in the md block are frequently referenced, so we load them into +independent variables in the hope that this will perform better. */ + +const pcre_uchar *start_subject = md->start_subject; +const pcre_uchar *end_subject = md->end_subject; +const pcre_uchar *start_code = md->start_code; + +#ifdef SUPPORT_UTF +BOOL utf = (md->poptions & PCRE_UTF8) != 0; +#else +BOOL utf = FALSE; +#endif + +rlevel++; +offsetcount &= (-2); + +wscount -= 2; +wscount = (wscount - (wscount % (INTS_PER_STATEBLOCK * 2))) / + (2 * INTS_PER_STATEBLOCK); + +DPRINTF(("\n%.*s---------------------\n" + "%.*sCall to internal_dfa_exec f=%d\n", + rlevel*2-2, SP, rlevel*2-2, SP, rlevel)); + +ctypes = md->tables + ctypes_offset; +lcc = md->tables + lcc_offset; +fcc = md->tables + fcc_offset; + +match_count = PCRE_ERROR_NOMATCH; /* A negative number */ + +active_states = (stateblock *)(workspace + 2); +next_new_state = new_states = active_states + wscount; +new_count = 0; + +first_op = this_start_code + 1 + LINK_SIZE + + ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || + *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) + ? IMM2_SIZE:0); + +/* The first thing in any (sub) pattern is a bracket of some sort. Push all +the alternative states onto the list, and find out where the end is. This +makes is possible to use this function recursively, when we want to stop at a +matching internal ket rather than at the end. + +If the first opcode in the first alternative is OP_REVERSE, we are dealing with +a backward assertion. In that case, we have to find out the maximum amount to +move back, and set up each alternative appropriately. */ + +if (*first_op == OP_REVERSE) + { + int max_back = 0; + int gone_back; + + end_code = this_start_code; + do + { + int back = GET(end_code, 2+LINK_SIZE); + if (back > max_back) max_back = back; + end_code += GET(end_code, 1); + } + while (*end_code == OP_ALT); + + /* If we can't go back the amount required for the longest lookbehind + pattern, go back as far as we can; some alternatives may still be viable. */ + +#ifdef SUPPORT_UTF + /* In character mode we have to step back character by character */ + + if (utf) + { + for (gone_back = 0; gone_back < max_back; gone_back++) + { + if (current_subject <= start_subject) break; + current_subject--; + ACROSSCHAR(current_subject > start_subject, *current_subject, current_subject--); + } + } + else +#endif + + /* In byte-mode we can do this quickly. */ + + { + gone_back = (current_subject - max_back < start_subject)? + (int)(current_subject - start_subject) : max_back; + current_subject -= gone_back; + } + + /* Save the earliest consulted character */ + + if (current_subject < md->start_used_ptr) + md->start_used_ptr = current_subject; + + /* Now we can process the individual branches. */ + + end_code = this_start_code; + do + { + int back = GET(end_code, 2+LINK_SIZE); + if (back <= gone_back) + { + int bstate = (int)(end_code - start_code + 2 + 2*LINK_SIZE); + ADD_NEW_DATA(-bstate, 0, gone_back - back); + } + end_code += GET(end_code, 1); + } + while (*end_code == OP_ALT); + } + +/* This is the code for a "normal" subpattern (not a backward assertion). The +start of a whole pattern is always one of these. If we are at the top level, +we may be asked to restart matching from the same point that we reached for a +previous partial match. We still have to scan through the top-level branches to +find the end state. */ + +else + { + end_code = this_start_code; + + /* Restarting */ + + if (rlevel == 1 && (md->moptions & PCRE_DFA_RESTART) != 0) + { + do { end_code += GET(end_code, 1); } while (*end_code == OP_ALT); + new_count = workspace[1]; + if (!workspace[0]) + memcpy(new_states, active_states, new_count * sizeof(stateblock)); + } + + /* Not restarting */ + + else + { + int length = 1 + LINK_SIZE + + ((*this_start_code == OP_CBRA || *this_start_code == OP_SCBRA || + *this_start_code == OP_CBRAPOS || *this_start_code == OP_SCBRAPOS) + ? IMM2_SIZE:0); + do + { + ADD_NEW((int)(end_code - start_code + length), 0); + end_code += GET(end_code, 1); + length = 1 + LINK_SIZE; + } + while (*end_code == OP_ALT); + } + } + +workspace[0] = 0; /* Bit indicating which vector is current */ + +DPRINTF(("%.*sEnd state = %d\n", rlevel*2-2, SP, (int)(end_code - start_code))); + +/* Loop for scanning the subject */ + +ptr = current_subject; +for (;;) + { + int i, j; + int clen, dlen; + unsigned int c, d; + int forced_fail = 0; + BOOL could_continue = FALSE; + + /* Make the new state list into the active state list and empty the + new state list. */ + + temp_states = active_states; + active_states = new_states; + new_states = temp_states; + active_count = new_count; + new_count = 0; + + workspace[0] ^= 1; /* Remember for the restarting feature */ + workspace[1] = active_count; + +#ifdef PCRE_DEBUG + printf("%.*sNext character: rest of subject = \"", rlevel*2-2, SP); + pchars(ptr, STRLEN_UC(ptr), stdout); + printf("\"\n"); + + printf("%.*sActive states: ", rlevel*2-2, SP); + for (i = 0; i < active_count; i++) + printf("%d/%d ", active_states[i].offset, active_states[i].count); + printf("\n"); +#endif + + /* Set the pointers for adding new states */ + + next_active_state = active_states + active_count; + next_new_state = new_states; + + /* Load the current character from the subject outside the loop, as many + different states may want to look at it, and we assume that at least one + will. */ + + if (ptr < end_subject) + { + clen = 1; /* Number of bytes in the character */ +#ifdef SUPPORT_UTF + if (utf) { GETCHARLEN(c, ptr, clen); } else +#endif /* SUPPORT_UTF */ + c = *ptr; + } + else + { + clen = 0; /* This indicates the end of the subject */ + c = NOTACHAR; /* This value should never actually be used */ + } + + /* Scan up the active states and act on each one. The result of an action + may be to add more states to the currently active list (e.g. on hitting a + parenthesis) or it may be to put states on the new list, for considering + when we move the character pointer on. */ + + for (i = 0; i < active_count; i++) + { + stateblock *current_state = active_states + i; + BOOL caseless = FALSE; + const pcre_uchar *code; + int state_offset = current_state->offset; + int count, codevalue, rrc; + +#ifdef PCRE_DEBUG + printf ("%.*sProcessing state %d c=", rlevel*2-2, SP, state_offset); + if (clen == 0) printf("EOL\n"); + else if (c > 32 && c < 127) printf("'%c'\n", c); + else printf("0x%02x\n", c); +#endif + + /* A negative offset is a special case meaning "hold off going to this + (negated) state until the number of characters in the data field have + been skipped". */ + + if (state_offset < 0) + { + if (current_state->data > 0) + { + DPRINTF(("%.*sSkipping this character\n", rlevel*2-2, SP)); + ADD_NEW_DATA(state_offset, current_state->count, + current_state->data - 1); + continue; + } + else + { + current_state->offset = state_offset = -state_offset; + } + } + + /* Check for a duplicate state with the same count, and skip if found. + See the note at the head of this module about the possibility of improving + performance here. */ + + for (j = 0; j < i; j++) + { + if (active_states[j].offset == state_offset && + active_states[j].count == current_state->count) + { + DPRINTF(("%.*sDuplicate state: skipped\n", rlevel*2-2, SP)); + goto NEXT_ACTIVE_STATE; + } + } + + /* The state offset is the offset to the opcode */ + + code = start_code + state_offset; + codevalue = *code; + + /* If this opcode inspects a character, but we are at the end of the + subject, remember the fact for use when testing for a partial match. */ + + if (clen == 0 && poptable[codevalue] != 0) + could_continue = TRUE; + + /* If this opcode is followed by an inline character, load it. It is + tempting to test for the presence of a subject character here, but that + is wrong, because sometimes zero repetitions of the subject are + permitted. + + We also use this mechanism for opcodes such as OP_TYPEPLUS that take an + argument that is not a data character - but is always one byte long. We + have to take special action to deal with \P, \p, \H, \h, \V, \v and \X in + this case. To keep the other cases fast, convert these ones to new opcodes. + */ + + if (coptable[codevalue] > 0) + { + dlen = 1; +#ifdef SUPPORT_UTF + if (utf) { GETCHARLEN(d, (code + coptable[codevalue]), dlen); } else +#endif /* SUPPORT_UTF */ + d = code[coptable[codevalue]]; + if (codevalue >= OP_TYPESTAR) + { + switch(d) + { + case OP_ANYBYTE: return PCRE_ERROR_DFA_UITEM; + case OP_NOTPROP: + case OP_PROP: codevalue += OP_PROP_EXTRA; break; + case OP_ANYNL: codevalue += OP_ANYNL_EXTRA; break; + case OP_EXTUNI: codevalue += OP_EXTUNI_EXTRA; break; + case OP_NOT_HSPACE: + case OP_HSPACE: codevalue += OP_HSPACE_EXTRA; break; + case OP_NOT_VSPACE: + case OP_VSPACE: codevalue += OP_VSPACE_EXTRA; break; + default: break; + } + } + } + else + { + dlen = 0; /* Not strictly necessary, but compilers moan */ + d = NOTACHAR; /* if these variables are not set. */ + } + + + /* Now process the individual opcodes */ + + switch (codevalue) + { +/* ========================================================================== */ + /* These cases are never obeyed. This is a fudge that causes a compile- + time error if the vectors coptable or poptable, which are indexed by + opcode, are not the correct length. It seems to be the only way to do + such a check at compile time, as the sizeof() operator does not work + in the C preprocessor. */ + + case OP_TABLE_LENGTH: + case OP_TABLE_LENGTH + + ((sizeof(coptable) == OP_TABLE_LENGTH) && + (sizeof(poptable) == OP_TABLE_LENGTH)): + break; + +/* ========================================================================== */ + /* Reached a closing bracket. If not at the end of the pattern, carry + on with the next opcode. For repeating opcodes, also add the repeat + state. Note that KETRPOS will always be encountered at the end of the + subpattern, because the possessive subpattern repeats are always handled + using recursive calls. Thus, it never adds any new states. + + At the end of the (sub)pattern, unless we have an empty string and + PCRE_NOTEMPTY is set, or PCRE_NOTEMPTY_ATSTART is set and we are at the + start of the subject, save the match data, shifting up all previous + matches so we always have the longest first. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + case OP_KETRPOS: + if (code != end_code) + { + ADD_ACTIVE(state_offset + 1 + LINK_SIZE, 0); + if (codevalue != OP_KET) + { + ADD_ACTIVE(state_offset - GET(code, 1), 0); + } + } + else + { + if (ptr > current_subject || + ((md->moptions & PCRE_NOTEMPTY) == 0 && + ((md->moptions & PCRE_NOTEMPTY_ATSTART) == 0 || + current_subject > start_subject + md->start_offset))) + { + if (match_count < 0) match_count = (offsetcount >= 2)? 1 : 0; + else if (match_count > 0 && ++match_count * 2 > offsetcount) + match_count = 0; + count = ((match_count == 0)? offsetcount : match_count * 2) - 2; + if (count > 0) memmove(offsets + 2, offsets, count * sizeof(int)); + if (offsetcount >= 2) + { + offsets[0] = (int)(current_subject - start_subject); + offsets[1] = (int)(ptr - start_subject); + DPRINTF(("%.*sSet matched string = \"%.*s\"\n", rlevel*2-2, SP, + offsets[1] - offsets[0], current_subject)); + } + if ((md->moptions & PCRE_DFA_SHORTEST) != 0) + { + DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" + "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, + match_count, rlevel*2-2, SP)); + return match_count; + } + } + } + break; + +/* ========================================================================== */ + /* These opcodes add to the current list of states without looking + at the current character. */ + + /*-----------------------------------------------------------------*/ + case OP_ALT: + do { code += GET(code, 1); } while (*code == OP_ALT); + ADD_ACTIVE((int)(code - start_code), 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_BRA: + case OP_SBRA: + do + { + ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); + code += GET(code, 1); + } + while (*code == OP_ALT); + break; + + /*-----------------------------------------------------------------*/ + case OP_CBRA: + case OP_SCBRA: + ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE + IMM2_SIZE), 0); + code += GET(code, 1); + while (*code == OP_ALT) + { + ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); + code += GET(code, 1); + } + break; + + /*-----------------------------------------------------------------*/ + case OP_BRAZERO: + case OP_BRAMINZERO: + ADD_ACTIVE(state_offset + 1, 0); + code += 1 + GET(code, 2); + while (*code == OP_ALT) code += GET(code, 1); + ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_SKIPZERO: + code += 1 + GET(code, 2); + while (*code == OP_ALT) code += GET(code, 1); + ADD_ACTIVE((int)(code - start_code + 1 + LINK_SIZE), 0); + break; + + /*-----------------------------------------------------------------*/ + case OP_CIRC: + if (ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_CIRCM: + if ((ptr == start_subject && (md->moptions & PCRE_NOTBOL) == 0) || + (ptr != end_subject && WAS_NEWLINE(ptr))) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_EOD: + if (ptr >= end_subject) + { + if ((md->moptions & PCRE_PARTIAL_HARD) != 0) + could_continue = TRUE; + else { ADD_ACTIVE(state_offset + 1, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_SOD: + if (ptr == start_subject) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_SOM: + if (ptr == start_subject + start_offset) { ADD_ACTIVE(state_offset + 1, 0); } + break; + + +/* ========================================================================== */ + /* These opcodes inspect the next subject character, and sometimes + the previous one as well, but do not have an argument. The variable + clen contains the length of the current character and is zero if we are + at the end of the subject. */ + + /*-----------------------------------------------------------------*/ + case OP_ANY: + if (clen > 0 && !IS_NEWLINE(ptr)) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_ALLANY: + if (clen > 0) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_EODN: + if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) + could_continue = TRUE; + else if (clen == 0 || (IS_NEWLINE(ptr) && ptr == end_subject - md->nllen)) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_DOLL: + if ((md->moptions & PCRE_NOTEOL) == 0) + { + if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) + could_continue = TRUE; + else if (clen == 0 || + ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr) && + (ptr == end_subject - md->nllen) + )) + { ADD_ACTIVE(state_offset + 1, 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_DOLLM: + if ((md->moptions & PCRE_NOTEOL) == 0) + { + if (clen == 0 && (md->moptions & PCRE_PARTIAL_HARD) != 0) + could_continue = TRUE; + else if (clen == 0 || + ((md->poptions & PCRE_DOLLAR_ENDONLY) == 0 && IS_NEWLINE(ptr))) + { ADD_ACTIVE(state_offset + 1, 0); } + } + else if (IS_NEWLINE(ptr)) + { ADD_ACTIVE(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + + case OP_DIGIT: + case OP_WHITESPACE: + case OP_WORDCHAR: + if (clen > 0 && c < 256 && + ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_NOT_DIGIT: + case OP_NOT_WHITESPACE: + case OP_NOT_WORDCHAR: + if (clen > 0 && (c >= 256 || + ((ctypes[c] & toptable1[codevalue]) ^ toptable2[codevalue]) != 0)) + { ADD_NEW(state_offset + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + { + int left_word, right_word; + + if (ptr > start_subject) + { + const pcre_uchar *temp = ptr - 1; + if (temp < md->start_used_ptr) md->start_used_ptr = temp; +#ifdef SUPPORT_UTF + if (utf) { BACKCHAR(temp); } +#endif + GETCHARTEST(d, temp); +#ifdef SUPPORT_UCP + if ((md->poptions & PCRE_UCP) != 0) + { + if (d == '_') left_word = TRUE; else + { + int cat = UCD_CATEGORY(d); + left_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + left_word = d < 256 && (ctypes[d] & ctype_word) != 0; + } + else left_word = FALSE; + + if (clen > 0) + { +#ifdef SUPPORT_UCP + if ((md->poptions & PCRE_UCP) != 0) + { + if (c == '_') right_word = TRUE; else + { + int cat = UCD_CATEGORY(c); + right_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + right_word = c < 256 && (ctypes[c] & ctype_word) != 0; + } + else right_word = FALSE; + + if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY)) + { ADD_ACTIVE(state_offset + 1, 0); } + } + break; + + + /*-----------------------------------------------------------------*/ + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. + */ + +#ifdef SUPPORT_UCP + case OP_PROP: + case OP_NOTPROP: + if (clen > 0) + { + BOOL OK; + const ucd_record * prop = GET_UCD(c); + switch(code[1]) + { + case PT_ANY: + OK = TRUE; + break; + + case PT_LAMP: + OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt; + break; + + case PT_GC: + OK = PRIV(ucp_gentype)[prop->chartype] == code[2]; + break; + + case PT_PC: + OK = prop->chartype == code[2]; + break; + + case PT_SC: + OK = prop->script == code[2]; + break; + + /* These are specials for combination cases. */ + + case PT_ALNUM: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; + break; + + case PT_PXSPACE: /* POSIX space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR; + break; + + case PT_WORD: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE; + break; + + /* Should never occur, but keep compilers from grumbling. */ + + default: + OK = codevalue != OP_PROP; + break; + } + + if (OK == (codevalue == OP_PROP)) { ADD_NEW(state_offset + 3, 0); } + } + break; +#endif + + + +/* ========================================================================== */ + /* These opcodes likewise inspect the subject character, but have an + argument that is not a data character. It is one of these opcodes: + OP_ANY, OP_ALLANY, OP_DIGIT, OP_NOT_DIGIT, OP_WHITESPACE, OP_NOT_SPACE, + OP_WORDCHAR, OP_NOT_WORDCHAR. The value is loaded into d. */ + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || !IS_NEWLINE(ptr)) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (count > 0 && codevalue == OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW(state_offset, count); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSQUERY: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || !IS_NEWLINE(ptr)) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (codevalue == OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW(state_offset + 2, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPOSSTAR: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || !IS_NEWLINE(ptr)) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (codevalue == OP_TYPEPOSSTAR) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW(state_offset, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEEXACT: + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || !IS_NEWLINE(ptr)) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + 1 + IMM2_SIZE + 1, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + if ((c >= 256 && d != OP_DIGIT && d != OP_WHITESPACE && d != OP_WORDCHAR) || + (c < 256 && + (d != OP_ANY || !IS_NEWLINE(ptr)) && + ((ctypes[c] & toptable1[d]) ^ toptable2[d]) != 0)) + { + if (codevalue == OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + 2 + IMM2_SIZE, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + +/* ========================================================================== */ + /* These are virtual opcodes that are used when something like + OP_TYPEPLUS has OP_PROP, OP_NOTPROP, OP_ANYNL, or OP_EXTUNI as its + argument. It keeps the code above fast for the other cases. The argument + is in the d variable. */ + +#ifdef SUPPORT_UCP + case OP_PROP_EXTRA + OP_TYPEPLUS: + case OP_PROP_EXTRA + OP_TYPEMINPLUS: + case OP_PROP_EXTRA + OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 4, 0); } + if (clen > 0) + { + BOOL OK; + const ucd_record * prop = GET_UCD(c); + switch(code[2]) + { + case PT_ANY: + OK = TRUE; + break; + + case PT_LAMP: + OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt; + break; + + case PT_GC: + OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; + break; + + case PT_PC: + OK = prop->chartype == code[3]; + break; + + case PT_SC: + OK = prop->script == code[3]; + break; + + /* These are specials for combination cases. */ + + case PT_ALNUM: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; + break; + + case PT_PXSPACE: /* POSIX space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR; + break; + + case PT_WORD: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE; + break; + + /* Should never occur, but keep compilers from grumbling. */ + + default: + OK = codevalue != OP_PROP; + break; + } + + if (OK == (d == OP_PROP)) + { + if (count > 0 && codevalue == OP_PROP_EXTRA + OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW(state_offset, count); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEPLUS: + case OP_EXTUNI_EXTRA + OP_TYPEMINPLUS: + case OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0 && UCD_CATEGORY(c) != ucp_M) + { + const pcre_uchar *nptr = ptr + clen; + int ncount = 0; + if (count > 0 && codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (UCD_CATEGORY(nd) != ucp_M) break; + ncount++; + nptr += ndlen; + } + count++; + ADD_NEW_DATA(-state_offset, count, ncount); + } + break; +#endif + + /*-----------------------------------------------------------------*/ + case OP_ANYNL_EXTRA + OP_TYPEPLUS: + case OP_ANYNL_EXTRA + OP_TYPEMINPLUS: + case OP_ANYNL_EXTRA + OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0) + { + int ncount = 0; + switch (c) + { + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; + goto ANYNL01; + + case 0x000d: + if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; + /* Fall through */ + + ANYNL01: + case 0x000a: + if (count > 0 && codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW_DATA(-state_offset, count, ncount); + break; + + default: + break; + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_VSPACE_EXTRA + OP_TYPEPLUS: + case OP_VSPACE_EXTRA + OP_TYPEMINPLUS: + case OP_VSPACE_EXTRA + OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x000a: + case 0x000b: + case 0x000c: + case 0x000d: + case 0x0085: + case 0x2028: + case 0x2029: + OK = TRUE; + break; + + default: + OK = FALSE; + break; + } + + if (OK == (d == OP_VSPACE)) + { + if (count > 0 && codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW_DATA(-state_offset, count, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_HSPACE_EXTRA + OP_TYPEPLUS: + case OP_HSPACE_EXTRA + OP_TYPEMINPLUS: + case OP_HSPACE_EXTRA + OP_TYPEPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + 2, 0); } + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + OK = TRUE; + break; + + default: + OK = FALSE; + break; + } + + if (OK == (d == OP_HSPACE)) + { + if (count > 0 && codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSPLUS) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW_DATA(-state_offset, count, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ +#ifdef SUPPORT_UCP + case OP_PROP_EXTRA + OP_TYPEQUERY: + case OP_PROP_EXTRA + OP_TYPEMINQUERY: + case OP_PROP_EXTRA + OP_TYPEPOSQUERY: + count = 4; + goto QS1; + + case OP_PROP_EXTRA + OP_TYPESTAR: + case OP_PROP_EXTRA + OP_TYPEMINSTAR: + case OP_PROP_EXTRA + OP_TYPEPOSSTAR: + count = 0; + + QS1: + + ADD_ACTIVE(state_offset + 4, 0); + if (clen > 0) + { + BOOL OK; + const ucd_record * prop = GET_UCD(c); + switch(code[2]) + { + case PT_ANY: + OK = TRUE; + break; + + case PT_LAMP: + OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt; + break; + + case PT_GC: + OK = PRIV(ucp_gentype)[prop->chartype] == code[3]; + break; + + case PT_PC: + OK = prop->chartype == code[3]; + break; + + case PT_SC: + OK = prop->script == code[3]; + break; + + /* These are specials for combination cases. */ + + case PT_ALNUM: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; + break; + + case PT_PXSPACE: /* POSIX space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR; + break; + + case PT_WORD: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE; + break; + + /* Should never occur, but keep compilers from grumbling. */ + + default: + OK = codevalue != OP_PROP; + break; + } + + if (OK == (d == OP_PROP)) + { + if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSSTAR || + codevalue == OP_PROP_EXTRA + OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW(state_offset + count, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEQUERY: + case OP_EXTUNI_EXTRA + OP_TYPEMINQUERY: + case OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY: + count = 2; + goto QS2; + + case OP_EXTUNI_EXTRA + OP_TYPESTAR: + case OP_EXTUNI_EXTRA + OP_TYPEMINSTAR: + case OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR: + count = 0; + + QS2: + + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0 && UCD_CATEGORY(c) != ucp_M) + { + const pcre_uchar *nptr = ptr + clen; + int ncount = 0; + if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSSTAR || + codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (UCD_CATEGORY(nd) != ucp_M) break; + ncount++; + nptr += ndlen; + } + ADD_NEW_DATA(-(state_offset + count), 0, ncount); + } + break; +#endif + + /*-----------------------------------------------------------------*/ + case OP_ANYNL_EXTRA + OP_TYPEQUERY: + case OP_ANYNL_EXTRA + OP_TYPEMINQUERY: + case OP_ANYNL_EXTRA + OP_TYPEPOSQUERY: + count = 2; + goto QS3; + + case OP_ANYNL_EXTRA + OP_TYPESTAR: + case OP_ANYNL_EXTRA + OP_TYPEMINSTAR: + case OP_ANYNL_EXTRA + OP_TYPEPOSSTAR: + count = 0; + + QS3: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + int ncount = 0; + switch (c) + { + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; + goto ANYNL02; + + case 0x000d: + if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; + /* Fall through */ + + ANYNL02: + case 0x000a: + if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSSTAR || + codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW_DATA(-(state_offset + count), 0, ncount); + break; + + default: + break; + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_VSPACE_EXTRA + OP_TYPEQUERY: + case OP_VSPACE_EXTRA + OP_TYPEMINQUERY: + case OP_VSPACE_EXTRA + OP_TYPEPOSQUERY: + count = 2; + goto QS4; + + case OP_VSPACE_EXTRA + OP_TYPESTAR: + case OP_VSPACE_EXTRA + OP_TYPEMINSTAR: + case OP_VSPACE_EXTRA + OP_TYPEPOSSTAR: + count = 0; + + QS4: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x000a: + case 0x000b: + case 0x000c: + case 0x000d: + case 0x0085: + case 0x2028: + case 0x2029: + OK = TRUE; + break; + + default: + OK = FALSE; + break; + } + if (OK == (d == OP_VSPACE)) + { + if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSSTAR || + codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW_DATA(-(state_offset + count), 0, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_HSPACE_EXTRA + OP_TYPEQUERY: + case OP_HSPACE_EXTRA + OP_TYPEMINQUERY: + case OP_HSPACE_EXTRA + OP_TYPEPOSQUERY: + count = 2; + goto QS5; + + case OP_HSPACE_EXTRA + OP_TYPESTAR: + case OP_HSPACE_EXTRA + OP_TYPEMINSTAR: + case OP_HSPACE_EXTRA + OP_TYPEPOSSTAR: + count = 0; + + QS5: + ADD_ACTIVE(state_offset + 2, 0); + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + OK = TRUE; + break; + + default: + OK = FALSE; + break; + } + + if (OK == (d == OP_HSPACE)) + { + if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSSTAR || + codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW_DATA(-(state_offset + count), 0, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ +#ifdef SUPPORT_UCP + case OP_PROP_EXTRA + OP_TYPEEXACT: + case OP_PROP_EXTRA + OP_TYPEUPTO: + case OP_PROP_EXTRA + OP_TYPEMINUPTO: + case OP_PROP_EXTRA + OP_TYPEPOSUPTO: + if (codevalue != OP_PROP_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 1 + IMM2_SIZE + 3, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + BOOL OK; + const ucd_record * prop = GET_UCD(c); + switch(code[1 + IMM2_SIZE + 1]) + { + case PT_ANY: + OK = TRUE; + break; + + case PT_LAMP: + OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt; + break; + + case PT_GC: + OK = PRIV(ucp_gentype)[prop->chartype] == code[1 + IMM2_SIZE + 2]; + break; + + case PT_PC: + OK = prop->chartype == code[1 + IMM2_SIZE + 2]; + break; + + case PT_SC: + OK = prop->script == code[1 + IMM2_SIZE + 2]; + break; + + /* These are specials for combination cases. */ + + case PT_ALNUM: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N; + break; + + case PT_SPACE: /* Perl space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR; + break; + + case PT_PXSPACE: /* POSIX space */ + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR; + break; + + case PT_WORD: + OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE; + break; + + /* Should never occur, but keep compilers from grumbling. */ + + default: + OK = codevalue != OP_PROP; + break; + } + + if (OK == (d == OP_PROP)) + { + if (codevalue == OP_PROP_EXTRA + OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + 1 + IMM2_SIZE + 3, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXTUNI_EXTRA + OP_TYPEEXACT: + case OP_EXTUNI_EXTRA + OP_TYPEUPTO: + case OP_EXTUNI_EXTRA + OP_TYPEMINUPTO: + case OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO: + if (codevalue != OP_EXTUNI_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0 && UCD_CATEGORY(c) != ucp_M) + { + const pcre_uchar *nptr = ptr + clen; + int ncount = 0; + if (codevalue == OP_EXTUNI_EXTRA + OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + while (nptr < end_subject) + { + int nd; + int ndlen = 1; + GETCHARLEN(nd, nptr, ndlen); + if (UCD_CATEGORY(nd) != ucp_M) break; + ncount++; + nptr += ndlen; + } + if (++count >= GET2(code, 1)) + { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } + else + { ADD_NEW_DATA(-state_offset, count, ncount); } + } + break; +#endif + + /*-----------------------------------------------------------------*/ + case OP_ANYNL_EXTRA + OP_TYPEEXACT: + case OP_ANYNL_EXTRA + OP_TYPEUPTO: + case OP_ANYNL_EXTRA + OP_TYPEMINUPTO: + case OP_ANYNL_EXTRA + OP_TYPEPOSUPTO: + if (codevalue != OP_ANYNL_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + int ncount = 0; + switch (c) + { + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; + goto ANYNL03; + + case 0x000d: + if (ptr + 1 < end_subject && ptr[1] == 0x0a) ncount = 1; + /* Fall through */ + + ANYNL03: + case 0x000a: + if (codevalue == OP_ANYNL_EXTRA + OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, ncount); } + else + { ADD_NEW_DATA(-state_offset, count, ncount); } + break; + + default: + break; + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_VSPACE_EXTRA + OP_TYPEEXACT: + case OP_VSPACE_EXTRA + OP_TYPEUPTO: + case OP_VSPACE_EXTRA + OP_TYPEMINUPTO: + case OP_VSPACE_EXTRA + OP_TYPEPOSUPTO: + if (codevalue != OP_VSPACE_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x000a: + case 0x000b: + case 0x000c: + case 0x000d: + case 0x0085: + case 0x2028: + case 0x2029: + OK = TRUE; + break; + + default: + OK = FALSE; + } + + if (OK == (d == OP_VSPACE)) + { + if (codevalue == OP_VSPACE_EXTRA + OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } + else + { ADD_NEW_DATA(-state_offset, count, 0); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_HSPACE_EXTRA + OP_TYPEEXACT: + case OP_HSPACE_EXTRA + OP_TYPEUPTO: + case OP_HSPACE_EXTRA + OP_TYPEMINUPTO: + case OP_HSPACE_EXTRA + OP_TYPEPOSUPTO: + if (codevalue != OP_HSPACE_EXTRA + OP_TYPEEXACT) + { ADD_ACTIVE(state_offset + 2 + IMM2_SIZE, 0); } + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + BOOL OK; + switch (c) + { + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + OK = TRUE; + break; + + default: + OK = FALSE; + break; + } + + if (OK == (d == OP_HSPACE)) + { + if (codevalue == OP_HSPACE_EXTRA + OP_TYPEPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW_DATA(-(state_offset + 2 + IMM2_SIZE), 0, 0); } + else + { ADD_NEW_DATA(-state_offset, count, 0); } + } + } + break; + +/* ========================================================================== */ + /* These opcodes are followed by a character that is usually compared + to the current subject character; it is loaded into d. We still get + here even if there is no subject character, because in some cases zero + repetitions are permitted. */ + + /*-----------------------------------------------------------------*/ + case OP_CHAR: + if (clen > 0 && c == d) { ADD_NEW(state_offset + dlen + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_CHARI: + if (clen == 0) break; + +#ifdef SUPPORT_UTF + if (utf) + { + if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else + { + unsigned int othercase; + if (c < 128) + othercase = fcc[c]; + else + /* If we have Unicode property support, we can use it to test the + other case of the character. */ +#ifdef SUPPORT_UCP + othercase = UCD_OTHERCASE(c); +#else + othercase = NOTACHAR; +#endif + + if (d == othercase) { ADD_NEW(state_offset + dlen + 1, 0); } + } + } + else +#endif /* SUPPORT_UTF */ + /* Not UTF mode */ + { + if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d)) + { ADD_NEW(state_offset + 2, 0); } + } + break; + + +#ifdef SUPPORT_UCP + /*-----------------------------------------------------------------*/ + /* This is a tricky one because it can match more than one character. + Find out how many characters to skip, and then set up a negative state + to wait for them to pass before continuing. */ + + case OP_EXTUNI: + if (clen > 0 && UCD_CATEGORY(c) != ucp_M) + { + const pcre_uchar *nptr = ptr + clen; + int ncount = 0; + while (nptr < end_subject) + { + int nclen = 1; + GETCHARLEN(c, nptr, nclen); + if (UCD_CATEGORY(c) != ucp_M) break; + ncount++; + nptr += nclen; + } + ADD_NEW_DATA(-(state_offset + 1), 0, ncount); + } + break; +#endif + + /*-----------------------------------------------------------------*/ + /* This is a tricky like EXTUNI because it too can match more than one + character (when CR is followed by LF). In this case, set up a negative + state to wait for one character to pass before continuing. */ + + case OP_ANYNL: + if (clen > 0) switch(c) + { + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if ((md->moptions & PCRE_BSR_ANYCRLF) != 0) break; + + case 0x000a: + ADD_NEW(state_offset + 1, 0); + break; + + case 0x000d: + if (ptr + 1 < end_subject && ptr[1] == 0x0a) + { + ADD_NEW_DATA(-(state_offset + 1), 0, 1); + } + else + { + ADD_NEW(state_offset + 1, 0); + } + break; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_NOT_VSPACE: + if (clen > 0) switch(c) + { + case 0x000a: + case 0x000b: + case 0x000c: + case 0x000d: + case 0x0085: + case 0x2028: + case 0x2029: + break; + + default: + ADD_NEW(state_offset + 1, 0); + break; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_VSPACE: + if (clen > 0) switch(c) + { + case 0x000a: + case 0x000b: + case 0x000c: + case 0x000d: + case 0x0085: + case 0x2028: + case 0x2029: + ADD_NEW(state_offset + 1, 0); + break; + + default: break; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_NOT_HSPACE: + if (clen > 0) switch(c) + { + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + break; + + default: + ADD_NEW(state_offset + 1, 0); + break; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_HSPACE: + if (clen > 0) switch(c) + { + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + ADD_NEW(state_offset + 1, 0); + break; + } + break; + + /*-----------------------------------------------------------------*/ + /* Match a negated single character casefully. This is only used for + one-byte characters, that is, we know that d < 256. The character we are + checking (c) can be multibyte. */ + + case OP_NOT: + if (clen > 0 && c != d) { ADD_NEW(state_offset + dlen + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + /* Match a negated single character caselessly. This is only used for + one-byte characters, that is, we know that d < 256. The character we are + checking (c) can be multibyte. */ + + case OP_NOTI: + if (clen > 0 && c != d && c != fcc[d]) + { ADD_NEW(state_offset + dlen + 1, 0); } + break; + + /*-----------------------------------------------------------------*/ + case OP_PLUSI: + case OP_MINPLUSI: + case OP_POSPLUSI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTPOSPLUSI: + caseless = TRUE; + codevalue -= OP_STARI - OP_STAR; + + /* Fall through */ + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTPOSPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(state_offset + dlen + 1, 0); } + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if (caseless) + { +#ifdef SUPPORT_UTF + if (utf && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF */ + otherd = TABLE_GET(d, fcc, d); + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (count > 0 && + (codevalue == OP_POSPLUS || codevalue == OP_NOTPOSPLUS)) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + count++; + ADD_NEW(state_offset, count); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_QUERYI: + case OP_MINQUERYI: + case OP_POSQUERYI: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTPOSQUERYI: + caseless = TRUE; + codevalue -= OP_STARI - OP_STAR; + /* Fall through */ + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTPOSQUERY: + ADD_ACTIVE(state_offset + dlen + 1, 0); + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if (caseless) + { +#ifdef SUPPORT_UTF + if (utf && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF */ + otherd = TABLE_GET(d, fcc, d); + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (codevalue == OP_POSQUERY || codevalue == OP_NOTPOSQUERY) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW(state_offset + dlen + 1, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_STARI: + case OP_MINSTARI: + case OP_POSSTARI: + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPOSSTARI: + caseless = TRUE; + codevalue -= OP_STARI - OP_STAR; + /* Fall through */ + case OP_STAR: + case OP_MINSTAR: + case OP_POSSTAR: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPOSSTAR: + ADD_ACTIVE(state_offset + dlen + 1, 0); + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if (caseless) + { +#ifdef SUPPORT_UTF + if (utf && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF */ + otherd = TABLE_GET(d, fcc, d); + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (codevalue == OP_POSSTAR || codevalue == OP_NOTPOSSTAR) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + ADD_NEW(state_offset, 0); + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_EXACTI: + case OP_NOTEXACTI: + caseless = TRUE; + codevalue -= OP_STARI - OP_STAR; + /* Fall through */ + case OP_EXACT: + case OP_NOTEXACT: + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if (caseless) + { +#ifdef SUPPORT_UTF + if (utf && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF */ + otherd = TABLE_GET(d, fcc, d); + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_UPTOI: + case OP_MINUPTOI: + case OP_POSUPTOI: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTPOSUPTOI: + caseless = TRUE; + codevalue -= OP_STARI - OP_STAR; + /* Fall through */ + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTPOSUPTO: + ADD_ACTIVE(state_offset + dlen + 1 + IMM2_SIZE, 0); + count = current_state->count; /* Number already matched */ + if (clen > 0) + { + unsigned int otherd = NOTACHAR; + if (caseless) + { +#ifdef SUPPORT_UTF + if (utf && d >= 128) + { +#ifdef SUPPORT_UCP + otherd = UCD_OTHERCASE(d); +#endif /* SUPPORT_UCP */ + } + else +#endif /* SUPPORT_UTF */ + otherd = TABLE_GET(d, fcc, d); + } + if ((c == d || c == otherd) == (codevalue < OP_NOTSTAR)) + { + if (codevalue == OP_POSUPTO || codevalue == OP_NOTPOSUPTO) + { + active_count--; /* Remove non-match possibility */ + next_active_state--; + } + if (++count >= GET2(code, 1)) + { ADD_NEW(state_offset + dlen + 1 + IMM2_SIZE, 0); } + else + { ADD_NEW(state_offset, count); } + } + } + break; + + +/* ========================================================================== */ + /* These are the class-handling opcodes */ + + case OP_CLASS: + case OP_NCLASS: + case OP_XCLASS: + { + BOOL isinclass = FALSE; + int next_state_offset; + const pcre_uchar *ecode; + + /* For a simple class, there is always just a 32-byte table, and we + can set isinclass from it. */ + + if (codevalue != OP_XCLASS) + { + ecode = code + 1 + (32 / sizeof(pcre_uchar)); + if (clen > 0) + { + isinclass = (c > 255)? (codevalue == OP_NCLASS) : + ((((pcre_uint8 *)(code + 1))[c/8] & (1 << (c&7))) != 0); + } + } + + /* An extended class may have a table or a list of single characters, + ranges, or both, and it may be positive or negative. There's a + function that sorts all this out. */ + + else + { + ecode = code + GET(code, 1); + if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf); + } + + /* At this point, isinclass is set for all kinds of class, and ecode + points to the byte after the end of the class. If there is a + quantifier, this is where it will be. */ + + next_state_offset = (int)(ecode - start_code); + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + ADD_ACTIVE(next_state_offset + 1, 0); + if (isinclass) { ADD_NEW(state_offset, 0); } + break; + + case OP_CRPLUS: + case OP_CRMINPLUS: + count = current_state->count; /* Already matched */ + if (count > 0) { ADD_ACTIVE(next_state_offset + 1, 0); } + if (isinclass) { count++; ADD_NEW(state_offset, count); } + break; + + case OP_CRQUERY: + case OP_CRMINQUERY: + ADD_ACTIVE(next_state_offset + 1, 0); + if (isinclass) { ADD_NEW(next_state_offset + 1, 0); } + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + count = current_state->count; /* Already matched */ + if (count >= GET2(ecode, 1)) + { ADD_ACTIVE(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } + if (isinclass) + { + int max = GET2(ecode, 1 + IMM2_SIZE); + if (++count >= max && max != 0) /* Max 0 => no limit */ + { ADD_NEW(next_state_offset + 1 + 2 * IMM2_SIZE, 0); } + else + { ADD_NEW(state_offset, count); } + } + break; + + default: + if (isinclass) { ADD_NEW(next_state_offset, 0); } + break; + } + } + break; + +/* ========================================================================== */ + /* These are the opcodes for fancy brackets of various kinds. We have + to use recursion in order to handle them. The "always failing" assertion + (?!) is optimised to OP_FAIL when compiling, so we have to support that, + though the other "backtracking verbs" are not supported. */ + + case OP_FAIL: + forced_fail++; /* Count FAILs for multiple states */ + break; + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + { + int rc; + int local_offsets[2]; + int local_workspace[1000]; + const pcre_uchar *endasscode = code + GET(code, 1); + + while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); + + rc = internal_dfa_exec( + md, /* static match data */ + code, /* this subexpression's code */ + ptr, /* where we currently are */ + (int)(ptr - start_subject), /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + rlevel); /* function recursion level */ + + if (rc == PCRE_ERROR_DFA_UITEM) return rc; + if ((rc >= 0) == (codevalue == OP_ASSERT || codevalue == OP_ASSERTBACK)) + { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_COND: + case OP_SCOND: + { + int local_offsets[1000]; + int local_workspace[1000]; + int codelink = GET(code, 1); + int condcode; + + /* Because of the way auto-callout works during compile, a callout item + is inserted between OP_COND and an assertion condition. This does not + happen for the other conditions. */ + + if (code[LINK_SIZE+1] == OP_CALLOUT) + { + rrc = 0; + if (PUBL(callout) != NULL) + { + PUBL(callout_block) cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = code[LINK_SIZE+2]; + cb.offset_vector = offsets; +#ifdef COMPILE_PCRE8 + cb.subject = (PCRE_SPTR)start_subject; +#else + cb.subject = (PCRE_SPTR16)start_subject; +#endif + cb.subject_length = (int)(end_subject - start_subject); + cb.start_match = (int)(current_subject - start_subject); + cb.current_position = (int)(ptr - start_subject); + cb.pattern_position = GET(code, LINK_SIZE + 3); + cb.next_item_length = GET(code, 3 + 2*LINK_SIZE); + cb.capture_top = 1; + cb.capture_last = -1; + cb.callout_data = md->callout_data; + cb.mark = NULL; /* No (*MARK) support */ + if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ + } + if (rrc > 0) break; /* Fail this thread */ + code += PRIV(OP_lengths)[OP_CALLOUT]; /* Skip callout data */ + } + + condcode = code[LINK_SIZE+1]; + + /* Back reference conditions are not supported */ + + if (condcode == OP_CREF || condcode == OP_NCREF) + return PCRE_ERROR_DFA_UCOND; + + /* The DEFINE condition is always false */ + + if (condcode == OP_DEF) + { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } + + /* The only supported version of OP_RREF is for the value RREF_ANY, + which means "test if in any recursion". We can't test for specifically + recursed groups. */ + + else if (condcode == OP_RREF || condcode == OP_NRREF) + { + int value = GET2(code, LINK_SIZE + 2); + if (value != RREF_ANY) return PCRE_ERROR_DFA_UCOND; + if (md->recursive != NULL) + { ADD_ACTIVE(state_offset + LINK_SIZE + 2 + IMM2_SIZE, 0); } + else { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } + } + + /* Otherwise, the condition is an assertion */ + + else + { + int rc; + const pcre_uchar *asscode = code + LINK_SIZE + 1; + const pcre_uchar *endasscode = asscode + GET(asscode, 1); + + while (*endasscode == OP_ALT) endasscode += GET(endasscode, 1); + + rc = internal_dfa_exec( + md, /* fixed match data */ + asscode, /* this subexpression's code */ + ptr, /* where we currently are */ + (int)(ptr - start_subject), /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + rlevel); /* function recursion level */ + + if (rc == PCRE_ERROR_DFA_UITEM) return rc; + if ((rc >= 0) == + (condcode == OP_ASSERT || condcode == OP_ASSERTBACK)) + { ADD_ACTIVE((int)(endasscode + LINK_SIZE + 1 - start_code), 0); } + else + { ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_RECURSE: + { + dfa_recursion_info *ri; + int local_offsets[1000]; + int local_workspace[1000]; + const pcre_uchar *callpat = start_code + GET(code, 1); + int recno = (callpat == md->start_code)? 0 : + GET2(callpat, 1 + LINK_SIZE); + int rc; + + DPRINTF(("%.*sStarting regex recursion\n", rlevel*2-2, SP)); + + /* Check for repeating a recursion without advancing the subject + pointer. This should catch convoluted mutual recursions. (Some simple + cases are caught at compile time.) */ + + for (ri = md->recursive; ri != NULL; ri = ri->prevrec) + if (recno == ri->group_num && ptr == ri->subject_position) + return PCRE_ERROR_RECURSELOOP; + + /* Remember this recursion and where we started it so as to + catch infinite loops. */ + + new_recursive.group_num = recno; + new_recursive.subject_position = ptr; + new_recursive.prevrec = md->recursive; + md->recursive = &new_recursive; + + rc = internal_dfa_exec( + md, /* fixed match data */ + callpat, /* this subexpression's code */ + ptr, /* where we currently are */ + (int)(ptr - start_subject), /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + rlevel); /* function recursion level */ + + md->recursive = new_recursive.prevrec; /* Done this recursion */ + + DPRINTF(("%.*sReturn from regex recursion: rc=%d\n", rlevel*2-2, SP, + rc)); + + /* Ran out of internal offsets */ + + if (rc == 0) return PCRE_ERROR_DFA_RECURSE; + + /* For each successful matched substring, set up the next state with a + count of characters to skip before trying it. Note that the count is in + characters, not bytes. */ + + if (rc > 0) + { + for (rc = rc*2 - 2; rc >= 0; rc -= 2) + { + int charcount = local_offsets[rc+1] - local_offsets[rc]; +#ifdef SUPPORT_UTF + const pcre_uchar *p = start_subject + local_offsets[rc]; + const pcre_uchar *pp = start_subject + local_offsets[rc+1]; + while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; +#endif + if (charcount > 0) + { + ADD_NEW_DATA(-(state_offset + LINK_SIZE + 1), 0, (charcount - 1)); + } + else + { + ADD_ACTIVE(state_offset + LINK_SIZE + 1, 0); + } + } + } + else if (rc != PCRE_ERROR_NOMATCH) return rc; + } + break; + + /*-----------------------------------------------------------------*/ + case OP_BRAPOS: + case OP_SBRAPOS: + case OP_CBRAPOS: + case OP_SCBRAPOS: + case OP_BRAPOSZERO: + { + int charcount, matched_count; + const pcre_uchar *local_ptr = ptr; + BOOL allow_zero; + + if (codevalue == OP_BRAPOSZERO) + { + allow_zero = TRUE; + codevalue = *(++code); /* Codevalue will be one of above BRAs */ + } + else allow_zero = FALSE; + + /* Loop to match the subpattern as many times as possible as if it were + a complete pattern. */ + + for (matched_count = 0;; matched_count++) + { + int local_offsets[2]; + int local_workspace[1000]; + + int rc = internal_dfa_exec( + md, /* fixed match data */ + code, /* this subexpression's code */ + local_ptr, /* where we currently are */ + (int)(ptr - start_subject), /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + rlevel); /* function recursion level */ + + /* Failed to match */ + + if (rc < 0) + { + if (rc != PCRE_ERROR_NOMATCH) return rc; + break; + } + + /* Matched: break the loop if zero characters matched. */ + + charcount = local_offsets[1] - local_offsets[0]; + if (charcount == 0) break; + local_ptr += charcount; /* Advance temporary position ptr */ + } + + /* At this point we have matched the subpattern matched_count + times, and local_ptr is pointing to the character after the end of the + last match. */ + + if (matched_count > 0 || allow_zero) + { + const pcre_uchar *end_subpattern = code; + int next_state_offset; + + do { end_subpattern += GET(end_subpattern, 1); } + while (*end_subpattern == OP_ALT); + next_state_offset = + (int)(end_subpattern - start_code + LINK_SIZE + 1); + + /* Optimization: if there are no more active states, and there + are no new states yet set up, then skip over the subject string + right here, to save looping. Otherwise, set up the new state to swing + into action when the end of the matched substring is reached. */ + + if (i + 1 >= active_count && new_count == 0) + { + ptr = local_ptr; + clen = 0; + ADD_NEW(next_state_offset, 0); + } + else + { + const pcre_uchar *p = ptr; + const pcre_uchar *pp = local_ptr; + charcount = (int)(pp - p); +#ifdef SUPPORT_UTF + while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; +#endif + ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); + } + } + } + break; + + /*-----------------------------------------------------------------*/ + case OP_ONCE: + case OP_ONCE_NC: + { + int local_offsets[2]; + int local_workspace[1000]; + + int rc = internal_dfa_exec( + md, /* fixed match data */ + code, /* this subexpression's code */ + ptr, /* where we currently are */ + (int)(ptr - start_subject), /* start offset */ + local_offsets, /* offset vector */ + sizeof(local_offsets)/sizeof(int), /* size of same */ + local_workspace, /* workspace vector */ + sizeof(local_workspace)/sizeof(int), /* size of same */ + rlevel); /* function recursion level */ + + if (rc >= 0) + { + const pcre_uchar *end_subpattern = code; + int charcount = local_offsets[1] - local_offsets[0]; + int next_state_offset, repeat_state_offset; + + do { end_subpattern += GET(end_subpattern, 1); } + while (*end_subpattern == OP_ALT); + next_state_offset = + (int)(end_subpattern - start_code + LINK_SIZE + 1); + + /* If the end of this subpattern is KETRMAX or KETRMIN, we must + arrange for the repeat state also to be added to the relevant list. + Calculate the offset, or set -1 for no repeat. */ + + repeat_state_offset = (*end_subpattern == OP_KETRMAX || + *end_subpattern == OP_KETRMIN)? + (int)(end_subpattern - start_code - GET(end_subpattern, 1)) : -1; + + /* If we have matched an empty string, add the next state at the + current character pointer. This is important so that the duplicate + checking kicks in, which is what breaks infinite loops that match an + empty string. */ + + if (charcount == 0) + { + ADD_ACTIVE(next_state_offset, 0); + } + + /* Optimization: if there are no more active states, and there + are no new states yet set up, then skip over the subject string + right here, to save looping. Otherwise, set up the new state to swing + into action when the end of the matched substring is reached. */ + + else if (i + 1 >= active_count && new_count == 0) + { + ptr += charcount; + clen = 0; + ADD_NEW(next_state_offset, 0); + + /* If we are adding a repeat state at the new character position, + we must fudge things so that it is the only current state. + Otherwise, it might be a duplicate of one we processed before, and + that would cause it to be skipped. */ + + if (repeat_state_offset >= 0) + { + next_active_state = active_states; + active_count = 0; + i = -1; + ADD_ACTIVE(repeat_state_offset, 0); + } + } + else + { +#ifdef SUPPORT_UTF + const pcre_uchar *p = start_subject + local_offsets[0]; + const pcre_uchar *pp = start_subject + local_offsets[1]; + while (p < pp) if (NOT_FIRSTCHAR(*p++)) charcount--; +#endif + ADD_NEW_DATA(-next_state_offset, 0, (charcount - 1)); + if (repeat_state_offset >= 0) + { ADD_NEW_DATA(-repeat_state_offset, 0, (charcount - 1)); } + } + } + else if (rc != PCRE_ERROR_NOMATCH) return rc; + } + break; + + +/* ========================================================================== */ + /* Handle callouts */ + + case OP_CALLOUT: + rrc = 0; + if (PUBL(callout) != NULL) + { + PUBL(callout_block) cb; + cb.version = 1; /* Version 1 of the callout block */ + cb.callout_number = code[1]; + cb.offset_vector = offsets; +#ifdef COMPILE_PCRE8 + cb.subject = (PCRE_SPTR)start_subject; +#else + cb.subject = (PCRE_SPTR16)start_subject; +#endif + cb.subject_length = (int)(end_subject - start_subject); + cb.start_match = (int)(current_subject - start_subject); + cb.current_position = (int)(ptr - start_subject); + cb.pattern_position = GET(code, 2); + cb.next_item_length = GET(code, 2 + LINK_SIZE); + cb.capture_top = 1; + cb.capture_last = -1; + cb.callout_data = md->callout_data; + cb.mark = NULL; /* No (*MARK) support */ + if ((rrc = (*PUBL(callout))(&cb)) < 0) return rrc; /* Abandon */ + } + if (rrc == 0) + { ADD_ACTIVE(state_offset + PRIV(OP_lengths)[OP_CALLOUT], 0); } + break; + + +/* ========================================================================== */ + default: /* Unsupported opcode */ + return PCRE_ERROR_DFA_UITEM; + } + + NEXT_ACTIVE_STATE: continue; + + } /* End of loop scanning active states */ + + /* We have finished the processing at the current subject character. If no + new states have been set for the next character, we have found all the + matches that we are going to find. If we are at the top level and partial + matching has been requested, check for appropriate conditions. + + The "forced_ fail" variable counts the number of (*F) encountered for the + character. If it is equal to the original active_count (saved in + workspace[1]) it means that (*F) was found on every active state. In this + case we don't want to give a partial match. + + The "could_continue" variable is true if a state could have continued but + for the fact that the end of the subject was reached. */ + + if (new_count <= 0) + { + if (rlevel == 1 && /* Top level, and */ + could_continue && /* Some could go on */ + forced_fail != workspace[1] && /* Not all forced fail & */ + ( /* either... */ + (md->moptions & PCRE_PARTIAL_HARD) != 0 /* Hard partial */ + || /* or... */ + ((md->moptions & PCRE_PARTIAL_SOFT) != 0 && /* Soft partial and */ + match_count < 0) /* no matches */ + ) && /* And... */ + ptr >= end_subject && /* Reached end of subject */ + ptr > md->start_used_ptr) /* Inspected non-empty string */ + { + if (offsetcount >= 2) + { + offsets[0] = (int)(md->start_used_ptr - start_subject); + offsets[1] = (int)(end_subject - start_subject); + } + match_count = PCRE_ERROR_PARTIAL; + } + + DPRINTF(("%.*sEnd of internal_dfa_exec %d: returning %d\n" + "%.*s---------------------\n\n", rlevel*2-2, SP, rlevel, match_count, + rlevel*2-2, SP)); + break; /* In effect, "return", but see the comment below */ + } + + /* One or more states are active for the next character. */ + + ptr += clen; /* Advance to next subject character */ + } /* Loop to move along the subject string */ + +/* Control gets here from "break" a few lines above. We do it this way because +if we use "return" above, we have compiler trouble. Some compilers warn if +there's nothing here because they think the function doesn't return a value. On +the other hand, if we put a dummy statement here, some more clever compilers +complain that it can't be reached. Sigh. */ + +return match_count; +} + + + + +/************************************************* +* Execute a Regular Expression - DFA engine * +*************************************************/ + +/* This external function applies a compiled re to a subject string using a DFA +engine. This function calls the internal function multiple times if the pattern +is not anchored. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets vector of match offsets + offsetcount size of same + workspace workspace vector + wscount size of same + +Returns: > 0 => number of match offset pairs placed in offsets + = 0 => offsets overflowed; longest matches are present + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_dfa_exec(const pcre *argument_re, const pcre_extra *extra_data, + const char *subject, int length, int start_offset, int options, int *offsets, + int offsetcount, int *workspace, int wscount) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_dfa_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, + PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, + int offsetcount, int *workspace, int wscount) +#endif +{ +REAL_PCRE *re = (REAL_PCRE *)argument_re; +dfa_match_data match_block; +dfa_match_data *md = &match_block; +BOOL utf, anchored, startline, firstline; +const pcre_uchar *current_subject, *end_subject; +const pcre_study_data *study = NULL; + +const pcre_uchar *req_char_ptr; +const pcre_uint8 *start_bits = NULL; +BOOL has_first_char = FALSE; +BOOL has_req_char = FALSE; +pcre_uchar first_char = 0; +pcre_uchar first_char2 = 0; +pcre_uchar req_char = 0; +pcre_uchar req_char2 = 0; +int newline; + +/* Plausibility checks */ + +if ((options & ~PUBLIC_DFA_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || workspace == NULL || + (offsets == NULL && offsetcount > 0)) return PCRE_ERROR_NULL; +if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; +if (wscount < 20) return PCRE_ERROR_DFA_WSSIZE; +if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; + +/* We need to find the pointer to any study data before we test for byte +flipping, so we scan the extra_data block first. This may set two fields in the +match block, so we must initialize them beforehand. However, the other fields +in the match block must not be set until after the byte flipping. */ + +md->tables = re->tables; +md->callout_data = NULL; + +if (extra_data != NULL) + { + unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) return PCRE_ERROR_DFA_UMLIMIT; + if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) + return PCRE_ERROR_DFA_UMLIMIT; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + md->callout_data = extra_data->callout_data; + if ((flags & PCRE_EXTRA_TABLES) != 0) + md->tables = extra_data->tables; + } + +/* Check that the first field in the block is the magic number. If it is not, +return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to +REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which +means that the pattern is likely compiled with different endianness. */ + +if (re->magic_number != MAGIC_NUMBER) + return re->magic_number == REVERSED_MAGIC_NUMBER? + PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; +if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; + +/* Set some local values */ + +current_subject = (const pcre_uchar *)subject + start_offset; +end_subject = (const pcre_uchar *)subject + length; +req_char_ptr = current_subject - 1; + +#ifdef SUPPORT_UTF +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +utf = (re->options & PCRE_UTF8) != 0; +#else +utf = FALSE; +#endif + +anchored = (options & (PCRE_ANCHORED|PCRE_DFA_RESTART)) != 0 || + (re->options & PCRE_ANCHORED) != 0; + +/* The remaining fixed data for passing around. */ + +md->start_code = (const pcre_uchar *)argument_re + + re->name_table_offset + re->name_count * re->name_entry_size; +md->start_subject = (const pcre_uchar *)subject; +md->end_subject = end_subject; +md->start_offset = start_offset; +md->moptions = options; +md->poptions = re->options; + +/* If the BSR option is not set at match time, copy what was set +at compile time. */ + +if ((md->moptions & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) == 0) + { + if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) + md->moptions |= re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE); +#ifdef BSR_ANYCRLF + else md->moptions |= PCRE_BSR_ANYCRLF; +#endif + } + +/* Handle different types of newline. The three bits give eight cases. If +nothing is set at run time, whatever was used at compile time applies. */ + +switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : (pcre_uint32)options) & + PCRE_NEWLINE_BITS) + { + case 0: newline = NEWLINE; break; /* Compile-time default */ + case PCRE_NEWLINE_CR: newline = CHAR_CR; break; + case PCRE_NEWLINE_LF: newline = CHAR_NL; break; + case PCRE_NEWLINE_CR+ + PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; + case PCRE_NEWLINE_ANY: newline = -1; break; + case PCRE_NEWLINE_ANYCRLF: newline = -2; break; + default: return PCRE_ERROR_BADNEWLINE; + } + +if (newline == -2) + { + md->nltype = NLTYPE_ANYCRLF; + } +else if (newline < 0) + { + md->nltype = NLTYPE_ANY; + } +else + { + md->nltype = NLTYPE_FIXED; + if (newline > 255) + { + md->nllen = 2; + md->nl[0] = (newline >> 8) & 255; + md->nl[1] = newline & 255; + } + else + { + md->nllen = 1; + md->nl[0] = newline; + } + } + +/* Check a UTF-8 string if required. Unfortunately there's no way of passing +back the character offset. */ + +#ifdef SUPPORT_UTF +if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) + { + int erroroffset; + int errorcode = PRIV(valid_utf)((pcre_uchar *)subject, length, &erroroffset); + if (errorcode != 0) + { + if (offsetcount >= 2) + { + offsets[0] = erroroffset; + offsets[1] = errorcode; + } + return (errorcode <= PCRE_UTF8_ERR5 && (options & PCRE_PARTIAL_HARD) != 0)? + PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; + } + if (start_offset > 0 && start_offset < length && + NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) + return PCRE_ERROR_BADUTF8_OFFSET; + } +#endif + +/* If the exec call supplied NULL for tables, use the inbuilt ones. This +is a feature that makes it possible to save compiled regex and re-use them +in other programs later. */ + +if (md->tables == NULL) md->tables = PRIV(default_tables); + +/* The "must be at the start of a line" flags are used in a loop when finding +where to start. */ + +startline = (re->flags & PCRE_STARTLINE) != 0; +firstline = (re->options & PCRE_FIRSTLINE) != 0; + +/* Set up the first character to match, if available. The first_byte value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->flags & PCRE_FIRSTSET) != 0) + { + has_first_char = TRUE; + first_char = first_char2 = (pcre_uchar)(re->first_char); + if ((re->flags & PCRE_FCH_CASELESS) != 0) + { + first_char2 = TABLE_GET(first_char, md->tables + fcc_offset, first_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (utf && first_char > 127) + first_char2 = UCD_OTHERCASE(first_char); +#endif + } + } + else + { + if (!startline && study != NULL && + (study->flags & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->flags & PCRE_REQCHSET) != 0) + { + has_req_char = TRUE; + req_char = req_char2 = (pcre_uchar)(re->req_char); + if ((re->flags & PCRE_RCH_CASELESS) != 0) + { + req_char2 = TABLE_GET(req_char, md->tables + fcc_offset, req_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (utf && req_char > 127) + req_char2 = UCD_OTHERCASE(req_char); +#endif + } + } + +/* Call the main matching function, looping for a non-anchored regex after a +failed match. If not restarting, perform certain optimizations at the start of +a match. */ + +for (;;) + { + int rc; + + if ((options & PCRE_DFA_RESTART) == 0) + { + const pcre_uchar *save_end_subject = end_subject; + + /* If firstline is TRUE, the start of the match is constrained to the first + line of a multiline string. Implement this by temporarily adjusting + end_subject so that we stop scanning at a newline. If the match fails at + the newline, later code breaks this loop. */ + + if (firstline) + { + PCRE_PUCHAR t = current_subject; +#ifdef SUPPORT_UTF + if (utf) + { + while (t < md->end_subject && !IS_NEWLINE(t)) + { + t++; + ACROSSCHAR(t < end_subject, *t, t++); + } + } + else +#endif + while (t < md->end_subject && !IS_NEWLINE(t)) t++; + end_subject = t; + } + + /* There are some optimizations that avoid running the match if a known + starting point is not found. However, there is an option that disables + these, for testing and for ensuring that all callouts do actually occur. + The option can be set in the regex by (*NO_START_OPT) or passed in + match-time options. */ + + if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) + { + /* Advance to a known first char. */ + + if (has_first_char) + { + if (first_char != first_char2) + while (current_subject < end_subject && + *current_subject != first_char && *current_subject != first_char2) + current_subject++; + else + while (current_subject < end_subject && + *current_subject != first_char) + current_subject++; + } + + /* Or to just after a linebreak for a multiline match if possible */ + + else if (startline) + { + if (current_subject > md->start_subject + start_offset) + { +#ifdef SUPPORT_UTF + if (utf) + { + while (current_subject < end_subject && + !WAS_NEWLINE(current_subject)) + { + current_subject++; + ACROSSCHAR(current_subject < end_subject, *current_subject, + current_subject++); + } + } + else +#endif + while (current_subject < end_subject && !WAS_NEWLINE(current_subject)) + current_subject++; + + /* If we have just passed a CR and the newline option is ANY or + ANYCRLF, and we are now at a LF, advance the match position by one + more character. */ + + if (current_subject[-1] == CHAR_CR && + (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && + current_subject < end_subject && + *current_subject == CHAR_NL) + current_subject++; + } + } + + /* Or to a non-unique first char after study */ + + else if (start_bits != NULL) + { + while (current_subject < end_subject) + { + register unsigned int c = *current_subject; +#ifndef COMPILE_PCRE8 + if (c > 255) c = 255; +#endif + if ((start_bits[c/8] & (1 << (c&7))) == 0) + { + current_subject++; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 + /* In non 8-bit mode, the iteration will stop for + characters > 255 at the beginning or not stop at all. */ + if (utf) + ACROSSCHAR(current_subject < end_subject, *current_subject, + current_subject++); +#endif + } + else break; + } + } + } + + /* Restore fudged end_subject */ + + end_subject = save_end_subject; + + /* The following two optimizations are disabled for partial matching or if + disabling is explicitly requested (and of course, by the test above, this + code is not obeyed when restarting after a partial match). */ + + if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && + (options & (PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT)) == 0) + { + /* If the pattern was studied, a minimum subject length may be set. This + is a lower bound; no actual string of that length may actually match the + pattern. Although the value is, strictly, in characters, we treat it as + bytes to avoid spending too much time in this optimization. */ + + if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && + (pcre_uint32)(end_subject - current_subject) < study->minlength) + return PCRE_ERROR_NOMATCH; + + /* If req_char is set, we know that that character must appear in the + subject for the match to succeed. If the first character is set, req_char + must be later in the subject; otherwise the test starts at the match + point. This optimization can save a huge amount of work in patterns with + nested unlimited repeats that aren't going to match. Writing separate + code for cased/caseless versions makes it go faster, as does using an + autoincrement and backing off on a match. + + HOWEVER: when the subject string is very, very long, searching to its end + can take a long time, and give bad performance on quite ordinary + patterns. This showed up when somebody was matching /^C/ on a 32-megabyte + string... so we don't do this when the string is sufficiently long. */ + + if (has_req_char && end_subject - current_subject < REQ_BYTE_MAX) + { + register PCRE_PUCHAR p = current_subject + (has_first_char? 1:0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_char_ptr) + { + if (req_char != req_char2) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_char || pp == req_char2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_char) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop, + which will cause a return or PCRE_ERROR_NOMATCH. */ + + if (p >= end_subject) break; + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_char_ptr = p; + } + } + } + } /* End of optimizations that are done when not restarting */ + + /* OK, now we can do the business */ + + md->start_used_ptr = current_subject; + md->recursive = NULL; + + rc = internal_dfa_exec( + md, /* fixed match data */ + md->start_code, /* this subexpression's code */ + current_subject, /* where we currently are */ + start_offset, /* start offset in subject */ + offsets, /* offset vector */ + offsetcount, /* size of same */ + workspace, /* workspace vector */ + wscount, /* size of same */ + 0); /* function recurse level */ + + /* Anything other than "no match" means we are done, always; otherwise, carry + on only if not anchored. */ + + if (rc != PCRE_ERROR_NOMATCH || anchored) return rc; + + /* Advance to the next subject character unless we are at the end of a line + and firstline is set. */ + + if (firstline && IS_NEWLINE(current_subject)) break; + current_subject++; +#ifdef SUPPORT_UTF + if (utf) + { + ACROSSCHAR(current_subject < end_subject, *current_subject, + current_subject++); + } +#endif + if (current_subject > end_subject) break; + + /* If we have just passed a CR and we are now at a LF, and the pattern does + not contain any explicit matches for \r or \n, and the newline option is CRLF + or ANY or ANYCRLF, advance the match position by one more character. */ + + if (current_subject[-1] == CHAR_CR && + current_subject < end_subject && + *current_subject == CHAR_NL && + (re->flags & PCRE_HASCRORLF) == 0 && + (md->nltype == NLTYPE_ANY || + md->nltype == NLTYPE_ANYCRLF || + md->nllen == 2)) + current_subject++; + + } /* "Bumpalong" loop */ + +return PCRE_ERROR_NOMATCH; +} + +/* End of pcre_dfa_exec.c */ diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c new file mode 100644 index 0000000000..2905808c83 --- /dev/null +++ b/src/3rdparty/pcre/pcre_exec.c @@ -0,0 +1,6960 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains pcre_exec(), the externally visible function that does +pattern matching using an NFA algorithm, trying to mimic Perl as closely as +possible. There are also some static supporting functions. */ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#define NLBLOCK md /* Block containing newline information */ +#define PSSTART start_subject /* Field containing processed string start */ +#define PSEND end_subject /* Field containing processed string end */ + +#include "pcre_internal.h" + +/* Undefine some potentially clashing cpp symbols */ + +#undef min +#undef max + +/* Values for setting in md->match_function_type to indicate two special types +of call to match(). We do it this way to save on using another stack variable, +as stack usage is to be discouraged. */ + +#define MATCH_CONDASSERT 1 /* Called to check a condition assertion */ +#define MATCH_CBEGROUP 2 /* Could-be-empty unlimited repeat group */ + +/* Non-error returns from the match() function. Error returns are externally +defined PCRE_ERROR_xxx codes, which are all negative. */ + +#define MATCH_MATCH 1 +#define MATCH_NOMATCH 0 + +/* Special internal returns from the match() function. Make them sufficiently +negative to avoid the external error codes. */ + +#define MATCH_ACCEPT (-999) +#define MATCH_COMMIT (-998) +#define MATCH_KETRPOS (-997) +#define MATCH_ONCE (-996) +#define MATCH_PRUNE (-995) +#define MATCH_SKIP (-994) +#define MATCH_SKIP_ARG (-993) +#define MATCH_THEN (-992) + +/* Maximum number of ints of offset to save on the stack for recursive calls. +If the offset vector is bigger, malloc is used. This should be a multiple of 3, +because the offset vector is always a multiple of 3 long. */ + +#define REC_STACK_SAVE_MAX 30 + +/* Min and max values for the common repeats; for the maxima, 0 => infinity */ + +static const char rep_min[] = { 0, 0, 1, 1, 0, 0 }; +static const char rep_max[] = { 0, 0, 0, 0, 1, 1 }; + + + +#ifdef PCRE_DEBUG +/************************************************* +* Debugging function to print chars * +*************************************************/ + +/* Print a sequence of chars in printable format, stopping at the end of the +subject if the requested. + +Arguments: + p points to characters + length number to print + is_subject TRUE if printing from within md->start_subject + md pointer to matching data block, if is_subject is TRUE + +Returns: nothing +*/ + +static void +pchars(const pcre_uchar *p, int length, BOOL is_subject, match_data *md) +{ +unsigned int c; +if (is_subject && length > md->end_subject - p) length = md->end_subject - p; +while (length-- > 0) + if (isprint(c = *(p++))) printf("%c", c); else printf("\\x%02x", c); +} +#endif + + + +/************************************************* +* Match a back-reference * +*************************************************/ + +/* Normally, if a back reference hasn't been set, the length that is passed is +negative, so the match always fails. However, in JavaScript compatibility mode, +the length passed is zero. Note that in caseless UTF-8 mode, the number of +subject bytes matched may be different to the number of reference bytes. + +Arguments: + offset index into the offset vector + eptr pointer into the subject + length length of reference to be matched (number of bytes) + md points to match data block + caseless TRUE if caseless + +Returns: < 0 if not matched, otherwise the number of subject bytes matched +*/ + +static int +match_ref(int offset, register PCRE_PUCHAR eptr, int length, match_data *md, + BOOL caseless) +{ +PCRE_PUCHAR eptr_start = eptr; +register PCRE_PUCHAR p = md->start_subject + md->offset_vector[offset]; + +#ifdef PCRE_DEBUG +if (eptr >= md->end_subject) + printf("matching subject "); +else + { + printf("matching subject "); + pchars(eptr, length, TRUE, md); + } +printf(" against backref "); +pchars(p, length, FALSE, md); +printf("\n"); +#endif + +/* Always fail if reference not set (and not JavaScript compatible). */ + +if (length < 0) return -1; + +/* Separate the caseless case for speed. In UTF-8 mode we can only do this +properly if Unicode properties are supported. Otherwise, we can check only +ASCII characters. */ + +if (caseless) + { +#ifdef SUPPORT_UTF +#ifdef SUPPORT_UCP + if (md->utf) + { + /* Match characters up to the end of the reference. NOTE: the number of + bytes matched may differ, because there are some characters whose upper and + lower case versions code as different numbers of bytes. For example, U+023A + (2 bytes in UTF-8) is the upper case version of U+2C65 (3 bytes in UTF-8); + a sequence of 3 of the former uses 6 bytes, as does a sequence of two of + the latter. It is important, therefore, to check the length along the + reference, not along the subject (earlier code did this wrong). */ + + PCRE_PUCHAR endptr = p + length; + while (p < endptr) + { + int c, d; + if (eptr >= md->end_subject) return -1; + GETCHARINC(c, eptr); + GETCHARINC(d, p); + if (c != d && c != UCD_OTHERCASE(d)) return -1; + } + } + else +#endif +#endif + + /* The same code works when not in UTF-8 mode and in UTF-8 mode when there + is no UCP support. */ + { + if (eptr + length > md->end_subject) return -1; + while (length-- > 0) + { + if (TABLE_GET(*p, md->lcc, *p) != TABLE_GET(*eptr, md->lcc, *eptr)) return -1; + p++; + eptr++; + } + } + } + +/* In the caseful case, we can just compare the bytes, whether or not we +are in UTF-8 mode. */ + +else + { + if (eptr + length > md->end_subject) return -1; + while (length-- > 0) if (*p++ != *eptr++) return -1; + } + +return (int)(eptr - eptr_start); +} + + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +The match() function is highly recursive, though not every recursive call +increases the recursive depth. Nevertheless, some regular expressions can cause +it to recurse to a great depth. I was writing for Unix, so I just let it call +itself recursively. This uses the stack for saving everything that has to be +saved for a recursive call. On Unix, the stack can be large, and this works +fine. + +It turns out that on some non-Unix-like systems there are problems with +programs that use a lot of stack. (This despite the fact that every last chip +has oodles of memory these days, and techniques for extending the stack have +been known for decades.) So.... + +There is a fudge, triggered by defining NO_RECURSE, which avoids recursive +calls by keeping local variables that need to be preserved in blocks of memory +obtained from malloc() instead instead of on the stack. Macros are used to +achieve this so that the actual code doesn't look very different to what it +always used to. + +The original heap-recursive code used longjmp(). However, it seems that this +can be very slow on some operating systems. Following a suggestion from Stan +Switzer, the use of longjmp() has been abolished, at the cost of having to +provide a unique number for each call to RMATCH. There is no way of generating +a sequence of numbers at compile time in C. I have given them names, to make +them stand out more clearly. + +Crude tests on x86 Linux show a small speedup of around 5-8%. However, on +FreeBSD, avoiding longjmp() more than halves the time taken to run the standard +tests. Furthermore, not using longjmp() means that local dynamic variables +don't have indeterminate values; this has meant that the frame size can be +reduced because the result can be "passed back" by straight setting of the +variable instead of being passed in the frame. +**************************************************************************** +***************************************************************************/ + +/* Numbers for RMATCH calls. When this list is changed, the code at HEAP_RETURN +below must be updated in sync. */ + +enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10, + RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20, + RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30, + RM31, RM32, RM33, RM34, RM35, RM36, RM37, RM38, RM39, RM40, + RM41, RM42, RM43, RM44, RM45, RM46, RM47, RM48, RM49, RM50, + RM51, RM52, RM53, RM54, RM55, RM56, RM57, RM58, RM59, RM60, + RM61, RM62, RM63, RM64, RM65, RM66 }; + +/* These versions of the macros use the stack, as normal. There are debugging +versions and production versions. Note that the "rw" argument of RMATCH isn't +actually used in this definition. */ + +#ifndef NO_RECURSE +#define REGISTER register + +#ifdef PCRE_DEBUG +#define RMATCH(ra,rb,rc,rd,re,rw) \ + { \ + printf("match() called in line %d\n", __LINE__); \ + rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1); \ + printf("to line %d\n", __LINE__); \ + } +#define RRETURN(ra) \ + { \ + printf("match() returned %d from line %d ", ra, __LINE__); \ + return ra; \ + } +#else +#define RMATCH(ra,rb,rc,rd,re,rw) \ + rrc = match(ra,rb,mstart,rc,rd,re,rdepth+1) +#define RRETURN(ra) return ra +#endif + +#else + + +/* These versions of the macros manage a private stack on the heap. Note that +the "rd" argument of RMATCH isn't actually used in this definition. It's the md +argument of match(), which never changes. */ + +#define REGISTER + +#define RMATCH(ra,rb,rc,rd,re,rw)\ + {\ + heapframe *newframe = (heapframe *)(PUBL(stack_malloc))(sizeof(heapframe));\ + if (newframe == NULL) RRETURN(PCRE_ERROR_NOMEMORY);\ + frame->Xwhere = rw; \ + newframe->Xeptr = ra;\ + newframe->Xecode = rb;\ + newframe->Xmstart = mstart;\ + newframe->Xoffset_top = rc;\ + newframe->Xeptrb = re;\ + newframe->Xrdepth = frame->Xrdepth + 1;\ + newframe->Xprevframe = frame;\ + frame = newframe;\ + DPRINTF(("restarting from line %d\n", __LINE__));\ + goto HEAP_RECURSE;\ + L_##rw:\ + DPRINTF(("jumped back to line %d\n", __LINE__));\ + } + +#define RRETURN(ra)\ + {\ + heapframe *oldframe = frame;\ + frame = oldframe->Xprevframe;\ + if (oldframe != &frame_zero) (PUBL(stack_free))(oldframe);\ + if (frame != NULL)\ + {\ + rrc = ra;\ + goto HEAP_RETURN;\ + }\ + return ra;\ + } + + +/* Structure for remembering the local variables in a private frame */ + +typedef struct heapframe { + struct heapframe *Xprevframe; + + /* Function arguments that may change */ + + PCRE_PUCHAR Xeptr; + const pcre_uchar *Xecode; + PCRE_PUCHAR Xmstart; + int Xoffset_top; + eptrblock *Xeptrb; + unsigned int Xrdepth; + + /* Function local variables */ + + PCRE_PUCHAR Xcallpat; +#ifdef SUPPORT_UTF + PCRE_PUCHAR Xcharptr; +#endif + PCRE_PUCHAR Xdata; + PCRE_PUCHAR Xnext; + PCRE_PUCHAR Xpp; + PCRE_PUCHAR Xprev; + PCRE_PUCHAR Xsaved_eptr; + + recursion_info Xnew_recursive; + + BOOL Xcur_is_word; + BOOL Xcondition; + BOOL Xprev_is_word; + +#ifdef SUPPORT_UCP + int Xprop_type; + int Xprop_value; + int Xprop_fail_result; + int Xoclength; + pcre_uchar Xocchars[6]; +#endif + + int Xcodelink; + int Xctype; + unsigned int Xfc; + int Xfi; + int Xlength; + int Xmax; + int Xmin; + int Xnumber; + int Xoffset; + int Xop; + int Xsave_capture_last; + int Xsave_offset1, Xsave_offset2, Xsave_offset3; + int Xstacksave[REC_STACK_SAVE_MAX]; + + eptrblock Xnewptrb; + + /* Where to jump back to */ + + int Xwhere; + +} heapframe; + +#endif + + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Match from current position * +*************************************************/ + +/* This function is called recursively in many circumstances. Whenever it +returns a negative (error) response, the outer incarnation must also return the +same response. */ + +/* These macros pack up tests that are used for partial matching, and which +appear several times in the code. We set the "hit end" flag if the pointer is +at the end of the subject and also past the start of the subject (i.e. +something has been matched). For hard partial matching, we then return +immediately. The second one is used when we already know we are past the end of +the subject. */ + +#define CHECK_PARTIAL()\ + if (md->partial != 0 && eptr >= md->end_subject && \ + eptr > md->start_used_ptr) \ + { \ + md->hitend = TRUE; \ + if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ + } + +#define SCHECK_PARTIAL()\ + if (md->partial != 0 && eptr > md->start_used_ptr) \ + { \ + md->hitend = TRUE; \ + if (md->partial > 1) RRETURN(PCRE_ERROR_PARTIAL); \ + } + + +/* Performance note: It might be tempting to extract commonly used fields from +the md structure (e.g. utf, end_subject) into individual variables to improve +performance. Tests using gcc on a SPARC disproved this; in the first case, it +made performance worse. + +Arguments: + eptr pointer to current character in subject + ecode pointer to current position in compiled code + mstart pointer to the current match start position (can be modified + by encountering \K) + offset_top current top pointer + md pointer to "static" info for the match + eptrb pointer to chain of blocks containing eptr at start of + brackets - for testing for empty matches + rdepth the recursion depth + +Returns: MATCH_MATCH if matched ) these values are >= 0 + MATCH_NOMATCH if failed to match ) + a negative MATCH_xxx value for PRUNE, SKIP, etc + a negative PCRE_ERROR_xxx value if aborted by an error condition + (e.g. stopped by repeated call or recursion limit) +*/ + +static int +match(REGISTER PCRE_PUCHAR eptr, REGISTER const pcre_uchar *ecode, + PCRE_PUCHAR mstart, int offset_top, match_data *md, eptrblock *eptrb, + unsigned int rdepth) +{ +/* These variables do not need to be preserved over recursion in this function, +so they can be ordinary variables in all cases. Mark some of them with +"register" because they are used a lot in loops. */ + +register int rrc; /* Returns from recursive calls */ +register int i; /* Used for loops not involving calls to RMATCH() */ +register unsigned int c; /* Character values not kept over RMATCH() calls */ +register BOOL utf; /* Local copy of UTF flag for speed */ + +BOOL minimize, possessive; /* Quantifier options */ +BOOL caseless; +int condcode; + +/* When recursion is not being used, all "local" variables that have to be +preserved over calls to RMATCH() are part of a "frame". We set up the top-level +frame on the stack here; subsequent instantiations are obtained from the heap +whenever RMATCH() does a "recursion". See the macro definitions above. Putting +the top-level on the stack rather than malloc-ing them all gives a performance +boost in many cases where there is not much "recursion". */ + +#ifdef NO_RECURSE +heapframe frame_zero; +heapframe *frame = &frame_zero; +frame->Xprevframe = NULL; /* Marks the top level */ + +/* Copy in the original argument variables */ + +frame->Xeptr = eptr; +frame->Xecode = ecode; +frame->Xmstart = mstart; +frame->Xoffset_top = offset_top; +frame->Xeptrb = eptrb; +frame->Xrdepth = rdepth; + +/* This is where control jumps back to to effect "recursion" */ + +HEAP_RECURSE: + +/* Macros make the argument variables come from the current frame */ + +#define eptr frame->Xeptr +#define ecode frame->Xecode +#define mstart frame->Xmstart +#define offset_top frame->Xoffset_top +#define eptrb frame->Xeptrb +#define rdepth frame->Xrdepth + +/* Ditto for the local variables */ + +#ifdef SUPPORT_UTF +#define charptr frame->Xcharptr +#endif +#define callpat frame->Xcallpat +#define codelink frame->Xcodelink +#define data frame->Xdata +#define next frame->Xnext +#define pp frame->Xpp +#define prev frame->Xprev +#define saved_eptr frame->Xsaved_eptr + +#define new_recursive frame->Xnew_recursive + +#define cur_is_word frame->Xcur_is_word +#define condition frame->Xcondition +#define prev_is_word frame->Xprev_is_word + +#ifdef SUPPORT_UCP +#define prop_type frame->Xprop_type +#define prop_value frame->Xprop_value +#define prop_fail_result frame->Xprop_fail_result +#define oclength frame->Xoclength +#define occhars frame->Xocchars +#endif + +#define ctype frame->Xctype +#define fc frame->Xfc +#define fi frame->Xfi +#define length frame->Xlength +#define max frame->Xmax +#define min frame->Xmin +#define number frame->Xnumber +#define offset frame->Xoffset +#define op frame->Xop +#define save_capture_last frame->Xsave_capture_last +#define save_offset1 frame->Xsave_offset1 +#define save_offset2 frame->Xsave_offset2 +#define save_offset3 frame->Xsave_offset3 +#define stacksave frame->Xstacksave + +#define newptrb frame->Xnewptrb + +/* When recursion is being used, local variables are allocated on the stack and +get preserved during recursion in the normal way. In this environment, fi and +i, and fc and c, can be the same variables. */ + +#else /* NO_RECURSE not defined */ +#define fi i +#define fc c + +/* Many of the following variables are used only in small blocks of the code. +My normal style of coding would have declared them within each of those blocks. +However, in order to accommodate the version of this code that uses an external +"stack" implemented on the heap, it is easier to declare them all here, so the +declarations can be cut out in a block. The only declarations within blocks +below are for variables that do not have to be preserved over a recursive call +to RMATCH(). */ + +#ifdef SUPPORT_UTF +const pcre_uchar *charptr; +#endif +const pcre_uchar *callpat; +const pcre_uchar *data; +const pcre_uchar *next; +PCRE_PUCHAR pp; +const pcre_uchar *prev; +PCRE_PUCHAR saved_eptr; + +recursion_info new_recursive; + +BOOL cur_is_word; +BOOL condition; +BOOL prev_is_word; + +#ifdef SUPPORT_UCP +int prop_type; +int prop_value; +int prop_fail_result; +int oclength; +pcre_uchar occhars[6]; +#endif + +int codelink; +int ctype; +int length; +int max; +int min; +int number; +int offset; +int op; +int save_capture_last; +int save_offset1, save_offset2, save_offset3; +int stacksave[REC_STACK_SAVE_MAX]; + +eptrblock newptrb; + +/* There is a special fudge for calling match() in a way that causes it to +measure the size of its basic stack frame when the stack is being used for +recursion. The second argument (ecode) being NULL triggers this behaviour. It +cannot normally ever be NULL. The return is the negated value of the frame +size. */ + +if (ecode == NULL) + { + if (rdepth == 0) + return match((PCRE_PUCHAR)&rdepth, NULL, NULL, 0, NULL, NULL, 1); + else + { + int len = (char *)&rdepth - (char *)eptr; + return (len > 0)? -len : len; + } + } +#endif /* NO_RECURSE */ + +/* To save space on the stack and in the heap frame, I have doubled up on some +of the local variables that are used only in localised parts of the code, but +still need to be preserved over recursive calls of match(). These macros define +the alternative names that are used. */ + +#define allow_zero cur_is_word +#define cbegroup condition +#define code_offset codelink +#define condassert condition +#define matched_once prev_is_word +#define foc number +#define save_mark data + +/* These statements are here to stop the compiler complaining about unitialized +variables. */ + +#ifdef SUPPORT_UCP +prop_value = 0; +prop_fail_result = 0; +#endif + + +/* This label is used for tail recursion, which is used in a few cases even +when NO_RECURSE is not defined, in order to reduce the amount of stack that is +used. Thanks to Ian Taylor for noticing this possibility and sending the +original patch. */ + +TAIL_RECURSE: + +/* OK, now we can get on with the real code of the function. Recursive calls +are specified by the macro RMATCH and RRETURN is used to return. When +NO_RECURSE is *not* defined, these just turn into a recursive call to match() +and a "return", respectively (possibly with some debugging if PCRE_DEBUG is +defined). However, RMATCH isn't like a function call because it's quite a +complicated macro. It has to be used in one particular way. This shouldn't, +however, impact performance when true recursion is being used. */ + +#ifdef SUPPORT_UTF +utf = md->utf; /* Local copy of the flag */ +#else +utf = FALSE; +#endif + +/* First check that we haven't called match() too many times, or that we +haven't exceeded the recursive call limit. */ + +if (md->match_call_count++ >= md->match_limit) RRETURN(PCRE_ERROR_MATCHLIMIT); +if (rdepth >= md->match_limit_recursion) RRETURN(PCRE_ERROR_RECURSIONLIMIT); + +/* At the start of a group with an unlimited repeat that may match an empty +string, the variable md->match_function_type is set to MATCH_CBEGROUP. It is +done this way to save having to use another function argument, which would take +up space on the stack. See also MATCH_CONDASSERT below. + +When MATCH_CBEGROUP is set, add the current subject pointer to the chain of +such remembered pointers, to be checked when we hit the closing ket, in order +to break infinite loops that match no characters. When match() is called in +other circumstances, don't add to the chain. The MATCH_CBEGROUP feature must +NOT be used with tail recursion, because the memory block that is used is on +the stack, so a new one may be required for each match(). */ + +if (md->match_function_type == MATCH_CBEGROUP) + { + newptrb.epb_saved_eptr = eptr; + newptrb.epb_prev = eptrb; + eptrb = &newptrb; + md->match_function_type = 0; + } + +/* Now start processing the opcodes. */ + +for (;;) + { + minimize = possessive = FALSE; + op = *ecode; + + switch(op) + { + case OP_MARK: + md->nomatch_mark = ecode + 2; + md->mark = NULL; /* In case previously set by assertion */ + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, + eptrb, RM55); + if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && + md->mark == NULL) md->mark = ecode + 2; + + /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an + argument, and we must check whether that argument matches this MARK's + argument. It is passed back in md->start_match_ptr (an overloading of that + variable). If it does match, we reset that variable to the current subject + position and return MATCH_SKIP. Otherwise, pass back the return code + unaltered. */ + + else if (rrc == MATCH_SKIP_ARG && + STRCMP_UC_UC(ecode + 2, md->start_match_ptr) == 0) + { + md->start_match_ptr = eptr; + RRETURN(MATCH_SKIP); + } + RRETURN(rrc); + + case OP_FAIL: + RRETURN(MATCH_NOMATCH); + + /* COMMIT overrides PRUNE, SKIP, and THEN */ + + case OP_COMMIT: + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM52); + if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && + rrc != MATCH_SKIP && rrc != MATCH_SKIP_ARG && + rrc != MATCH_THEN) + RRETURN(rrc); + RRETURN(MATCH_COMMIT); + + /* PRUNE overrides THEN */ + + case OP_PRUNE: + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM51); + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + RRETURN(MATCH_PRUNE); + + case OP_PRUNE_ARG: + md->nomatch_mark = ecode + 2; + md->mark = NULL; /* In case previously set by assertion */ + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, + eptrb, RM56); + if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && + md->mark == NULL) md->mark = ecode + 2; + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + RRETURN(MATCH_PRUNE); + + /* SKIP overrides PRUNE and THEN */ + + case OP_SKIP: + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM53); + if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) + RRETURN(rrc); + md->start_match_ptr = eptr; /* Pass back current position */ + RRETURN(MATCH_SKIP); + + /* Note that, for Perl compatibility, SKIP with an argument does NOT set + nomatch_mark. There is a flag that disables this opcode when re-matching a + pattern that ended with a SKIP for which there was not a matching MARK. */ + + case OP_SKIP_ARG: + if (md->ignore_skip_arg) + { + ecode += PRIV(OP_lengths)[*ecode] + ecode[1]; + break; + } + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md, + eptrb, RM57); + if (rrc != MATCH_NOMATCH && rrc != MATCH_PRUNE && rrc != MATCH_THEN) + RRETURN(rrc); + + /* Pass back the current skip name by overloading md->start_match_ptr and + returning the special MATCH_SKIP_ARG return code. This will either be + caught by a matching MARK, or get to the top, where it causes a rematch + with the md->ignore_skip_arg flag set. */ + + md->start_match_ptr = ecode + 2; + RRETURN(MATCH_SKIP_ARG); + + /* For THEN (and THEN_ARG) we pass back the address of the opcode, so that + the branch in which it occurs can be determined. Overload the start of + match pointer to do this. */ + + case OP_THEN: + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM54); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->start_match_ptr = ecode; + RRETURN(MATCH_THEN); + + case OP_THEN_ARG: + md->nomatch_mark = ecode + 2; + md->mark = NULL; /* In case previously set by assertion */ + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, + md, eptrb, RM58); + if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) && + md->mark == NULL) md->mark = ecode + 2; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->start_match_ptr = ecode; + RRETURN(MATCH_THEN); + + /* Handle an atomic group that does not contain any capturing parentheses. + This can be handled like an assertion. Prior to 8.13, all atomic groups + were handled this way. In 8.13, the code was changed as below for ONCE, so + that backups pass through the group and thereby reset captured values. + However, this uses a lot more stack, so in 8.20, atomic groups that do not + contain any captures generate OP_ONCE_NC, which can be handled in the old, + less stack intensive way. + + Check the alternative branches in turn - the matching won't pass the KET + for this kind of subpattern. If any one branch matches, we carry on as at + the end of a normal bracket, leaving the subject pointer, but resetting + the start-of-match value in case it was changed by \K. */ + + case OP_ONCE_NC: + prev = ecode; + saved_eptr = eptr; + save_mark = md->mark; + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM64); + if (rrc == MATCH_MATCH) /* Note: _not_ MATCH_ACCEPT */ + { + mstart = md->start_match_ptr; + break; + } + if (rrc == MATCH_THEN) + { + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode,1); + md->mark = save_mark; + } + while (*ecode == OP_ALT); + + /* If hit the end of the group (which could be repeated), fail */ + + if (*ecode != OP_ONCE_NC && *ecode != OP_ALT) RRETURN(MATCH_NOMATCH); + + /* Continue as from after the group, updating the offsets high water + mark, since extracts may have been taken. */ + + do ecode += GET(ecode, 1); while (*ecode == OP_ALT); + + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + + /* For a non-repeating ket, just continue at this level. This also + happens for a repeating ket if no characters were matched in the group. + This is the forcible breaking of infinite loops as implemented in Perl + 5.005. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + ecode += 1+LINK_SIZE; + break; + } + + /* The repeating kets try the rest of the pattern or restart from the + preceding bracket, in the appropriate order. The second "call" of match() + uses tail recursion, to avoid using another stack frame. */ + + if (*ecode == OP_KETRMIN) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM65); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode = prev; + goto TAIL_RECURSE; + } + else /* OP_KETRMAX */ + { + md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, prev, offset_top, md, eptrb, RM66); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += 1 + LINK_SIZE; + goto TAIL_RECURSE; + } + /* Control never gets here */ + + /* Handle a capturing bracket, other than those that are possessive with an + unlimited repeat. If there is space in the offset vector, save the current + subject position in the working slot at the top of the vector. We mustn't + change the current values of the data slot, because they may be set from a + previous iteration of this group, and be referred to by a reference inside + the group. A failure to match might occur after the group has succeeded, + if something later on doesn't match. For this reason, we need to restore + the working value and also the values of the final offsets, in case they + were set by a previous iteration of the same bracket. + + If there isn't enough space in the offset vector, treat this as if it were + a non-capturing bracket. Don't worry about setting the flag for the error + case here; that is handled in the code for KET. */ + + case OP_CBRA: + case OP_SCBRA: + number = GET2(ecode, 1+LINK_SIZE); + offset = number << 1; + +#ifdef PCRE_DEBUG + printf("start bracket %d\n", number); + printf("subject="); + pchars(eptr, 16, TRUE, md); + printf("\n"); +#endif + + if (offset < md->offset_max) + { + save_offset1 = md->offset_vector[offset]; + save_offset2 = md->offset_vector[offset+1]; + save_offset3 = md->offset_vector[md->offset_end - number]; + save_capture_last = md->capture_last; + save_mark = md->mark; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + md->offset_vector[md->offset_end - number] = + (int)(eptr - md->start_subject); + + for (;;) + { + if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM1); + if (rrc == MATCH_ONCE) break; /* Backing up through an atomic group */ + + /* If we backed up to a THEN, check whether it is within the current + branch by comparing the address of the THEN that is passed back with + the end of the branch. If it is within the current branch, and the + branch is one of two or more alternatives (it either starts or ends + with OP_ALT), we have reached the limit of THEN's action, so convert + the return code to NOMATCH, which will cause normal backtracking to + happen from now on. Otherwise, THEN is passed back to an outer + alternative. This implements Perl's treatment of parenthesized groups, + where a group not containing | does not affect the current alternative, + that is, (X) is NOT the same as (X|(*F)). */ + + if (rrc == MATCH_THEN) + { + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + /* Anything other than NOMATCH is passed back. */ + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + md->mark = save_mark; + if (*ecode != OP_ALT) break; + } + + DPRINTF(("bracket %d failed\n", number)); + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + + /* At this point, rrc will be one of MATCH_ONCE or MATCH_NOMATCH. */ + + RRETURN(rrc); + } + + /* FALL THROUGH ... Insufficient room for saving captured contents. Treat + as a non-capturing bracket. */ + + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + + DPRINTF(("insufficient capture room: treat as non-capturing\n")); + + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + + /* Non-capturing or atomic group, except for possessive with unlimited + repeat and ONCE group with no captures. Loop for all the alternatives. + + When we get to the final alternative within the brackets, we used to return + the result of a recursive call to match() whatever happened so it was + possible to reduce stack usage by turning this into a tail recursion, + except in the case of a possibly empty group. However, now that there is + the possiblity of (*THEN) occurring in the final alternative, this + optimization is no longer always possible. + + We can optimize if we know there are no (*THEN)s in the pattern; at present + this is the best that can be done. + + MATCH_ONCE is returned when the end of an atomic group is successfully + reached, but subsequent matching fails. It passes back up the tree (causing + captured values to be reset) until the original atomic group level is + reached. This is tested by comparing md->once_target with the start of the + group. At this point, the return is converted into MATCH_NOMATCH so that + previous backup points can be taken. */ + + case OP_ONCE: + case OP_BRA: + case OP_SBRA: + DPRINTF(("start non-capturing bracket\n")); + + for (;;) + { + if (op >= OP_SBRA || op == OP_ONCE) md->match_function_type = MATCH_CBEGROUP; + + /* If this is not a possibly empty group, and there are no (*THEN)s in + the pattern, and this is the final alternative, optimize as described + above. */ + + else if (!md->hasthen && ecode[GET(ecode, 1)] != OP_ALT) + { + ecode += PRIV(OP_lengths)[*ecode]; + goto TAIL_RECURSE; + } + + /* In all other cases, we have to make another call to match(). */ + + save_mark = md->mark; + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, eptrb, + RM2); + + /* See comment in the code for capturing groups above about handling + THEN. */ + + if (rrc == MATCH_THEN) + { + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + if (rrc != MATCH_NOMATCH) + { + if (rrc == MATCH_ONCE) + { + const pcre_uchar *scode = ecode; + if (*scode != OP_ONCE) /* If not at start, find it */ + { + while (*scode == OP_ALT) scode += GET(scode, 1); + scode -= GET(scode, 1); + } + if (md->once_target == scode) rrc = MATCH_NOMATCH; + } + RRETURN(rrc); + } + ecode += GET(ecode, 1); + md->mark = save_mark; + if (*ecode != OP_ALT) break; + } + + RRETURN(MATCH_NOMATCH); + + /* Handle possessive capturing brackets with an unlimited repeat. We come + here from BRAZERO with allow_zero set TRUE. The offset_vector values are + handled similarly to the normal case above. However, the matching is + different. The end of these brackets will always be OP_KETRPOS, which + returns MATCH_KETRPOS without going further in the pattern. By this means + we can handle the group by iteration rather than recursion, thereby + reducing the amount of stack needed. */ + + case OP_CBRAPOS: + case OP_SCBRAPOS: + allow_zero = FALSE; + + POSSESSIVE_CAPTURE: + number = GET2(ecode, 1+LINK_SIZE); + offset = number << 1; + +#ifdef PCRE_DEBUG + printf("start possessive bracket %d\n", number); + printf("subject="); + pchars(eptr, 16, TRUE, md); + printf("\n"); +#endif + + if (offset < md->offset_max) + { + matched_once = FALSE; + code_offset = (int)(ecode - md->start_code); + + save_offset1 = md->offset_vector[offset]; + save_offset2 = md->offset_vector[offset+1]; + save_offset3 = md->offset_vector[md->offset_end - number]; + save_capture_last = md->capture_last; + + DPRINTF(("saving %d %d %d\n", save_offset1, save_offset2, save_offset3)); + + /* Each time round the loop, save the current subject position for use + when the group matches. For MATCH_MATCH, the group has matched, so we + restart it with a new subject starting position, remembering that we had + at least one match. For MATCH_NOMATCH, carry on with the alternatives, as + usual. If we haven't matched any alternatives in any iteration, check to + see if a previous iteration matched. If so, the group has matched; + continue from afterwards. Otherwise it has failed; restore the previous + capture values before returning NOMATCH. */ + + for (;;) + { + md->offset_vector[md->offset_end - number] = + (int)(eptr - md->start_subject); + if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM63); + if (rrc == MATCH_KETRPOS) + { + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + ecode = md->start_code + code_offset; + save_capture_last = md->capture_last; + matched_once = TRUE; + continue; + } + + /* See comment in the code for capturing groups above about handling + THEN. */ + + if (rrc == MATCH_THEN) + { + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->capture_last = save_capture_last; + ecode += GET(ecode, 1); + if (*ecode != OP_ALT) break; + } + + if (!matched_once) + { + md->offset_vector[offset] = save_offset1; + md->offset_vector[offset+1] = save_offset2; + md->offset_vector[md->offset_end - number] = save_offset3; + } + + if (allow_zero || matched_once) + { + ecode += 1 + LINK_SIZE; + break; + } + + RRETURN(MATCH_NOMATCH); + } + + /* FALL THROUGH ... Insufficient room for saving captured contents. Treat + as a non-capturing bracket. */ + + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + + DPRINTF(("insufficient capture room: treat as non-capturing\n")); + + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + /* VVVVVVVVVVVVVVVVVVVVVVVVV */ + + /* Non-capturing possessive bracket with unlimited repeat. We come here + from BRAZERO with allow_zero = TRUE. The code is similar to the above, + without the capturing complication. It is written out separately for speed + and cleanliness. */ + + case OP_BRAPOS: + case OP_SBRAPOS: + allow_zero = FALSE; + + POSSESSIVE_NON_CAPTURE: + matched_once = FALSE; + code_offset = (int)(ecode - md->start_code); + + for (;;) + { + if (op >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode], offset_top, md, + eptrb, RM48); + if (rrc == MATCH_KETRPOS) + { + offset_top = md->end_offset_top; + eptr = md->end_match_ptr; + ecode = md->start_code + code_offset; + matched_once = TRUE; + continue; + } + + /* See comment in the code for capturing groups above about handling + THEN. */ + + if (rrc == MATCH_THEN) + { + next = ecode + GET(ecode,1); + if (md->start_match_ptr < next && + (*ecode == OP_ALT || *next == OP_ALT)) + rrc = MATCH_NOMATCH; + } + + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode += GET(ecode, 1); + if (*ecode != OP_ALT) break; + } + + if (matched_once || allow_zero) + { + ecode += 1 + LINK_SIZE; + break; + } + RRETURN(MATCH_NOMATCH); + + /* Control never reaches here. */ + + /* Conditional group: compilation checked that there are no more than + two branches. If the condition is false, skipping the first branch takes us + past the end if there is only one branch, but that's OK because that is + exactly what going to the ket would do. */ + + case OP_COND: + case OP_SCOND: + codelink = GET(ecode, 1); + + /* Because of the way auto-callout works during compile, a callout item is + inserted between OP_COND and an assertion condition. */ + + if (ecode[LINK_SIZE+1] == OP_CALLOUT) + { + if (PUBL(callout) != NULL) + { + PUBL(callout_block) cb; + cb.version = 2; /* Version 1 of the callout block */ + cb.callout_number = ecode[LINK_SIZE+2]; + cb.offset_vector = md->offset_vector; +#ifdef COMPILE_PCRE8 + cb.subject = (PCRE_SPTR)md->start_subject; +#else + cb.subject = (PCRE_SPTR16)md->start_subject; +#endif + cb.subject_length = (int)(md->end_subject - md->start_subject); + cb.start_match = (int)(mstart - md->start_subject); + cb.current_position = (int)(eptr - md->start_subject); + cb.pattern_position = GET(ecode, LINK_SIZE + 3); + cb.next_item_length = GET(ecode, 3 + 2*LINK_SIZE); + cb.capture_top = offset_top/2; + cb.capture_last = md->capture_last; + cb.callout_data = md->callout_data; + cb.mark = md->nomatch_mark; + if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + } + ecode += PRIV(OP_lengths)[OP_CALLOUT]; + } + + condcode = ecode[LINK_SIZE+1]; + + /* Now see what the actual condition is */ + + if (condcode == OP_RREF || condcode == OP_NRREF) /* Recursion test */ + { + if (md->recursive == NULL) /* Not recursing => FALSE */ + { + condition = FALSE; + ecode += GET(ecode, 1); + } + else + { + int recno = GET2(ecode, LINK_SIZE + 2); /* Recursion group number*/ + condition = (recno == RREF_ANY || recno == md->recursive->group_num); + + /* If the test is for recursion into a specific subpattern, and it is + false, but the test was set up by name, scan the table to see if the + name refers to any other numbers, and test them. The condition is true + if any one is set. */ + + if (!condition && condcode == OP_NRREF) + { + pcre_uchar *slotA = md->name_table; + for (i = 0; i < md->name_count; i++) + { + if (GET2(slotA, 0) == recno) break; + slotA += md->name_entry_size; + } + + /* Found a name for the number - there can be only one; duplicate + names for different numbers are allowed, but not vice versa. First + scan down for duplicates. */ + + if (i < md->name_count) + { + pcre_uchar *slotB = slotA; + while (slotB > md->name_table) + { + slotB -= md->name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = GET2(slotB, 0) == md->recursive->group_num; + if (condition) break; + } + else break; + } + + /* Scan up for duplicates */ + + if (!condition) + { + slotB = slotA; + for (i++; i < md->name_count; i++) + { + slotB += md->name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = GET2(slotB, 0) == md->recursive->group_num; + if (condition) break; + } + else break; + } + } + } + } + + /* Chose branch according to the condition */ + + ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1); + } + } + + else if (condcode == OP_CREF || condcode == OP_NCREF) /* Group used test */ + { + offset = GET2(ecode, LINK_SIZE+2) << 1; /* Doubled ref number */ + condition = offset < offset_top && md->offset_vector[offset] >= 0; + + /* If the numbered capture is unset, but the reference was by name, + scan the table to see if the name refers to any other numbers, and test + them. The condition is true if any one is set. This is tediously similar + to the code above, but not close enough to try to amalgamate. */ + + if (!condition && condcode == OP_NCREF) + { + int refno = offset >> 1; + pcre_uchar *slotA = md->name_table; + + for (i = 0; i < md->name_count; i++) + { + if (GET2(slotA, 0) == refno) break; + slotA += md->name_entry_size; + } + + /* Found a name for the number - there can be only one; duplicate names + for different numbers are allowed, but not vice versa. First scan down + for duplicates. */ + + if (i < md->name_count) + { + pcre_uchar *slotB = slotA; + while (slotB > md->name_table) + { + slotB -= md->name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + offset = GET2(slotB, 0) << 1; + condition = offset < offset_top && + md->offset_vector[offset] >= 0; + if (condition) break; + } + else break; + } + + /* Scan up for duplicates */ + + if (!condition) + { + slotB = slotA; + for (i++; i < md->name_count; i++) + { + slotB += md->name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + offset = GET2(slotB, 0) << 1; + condition = offset < offset_top && + md->offset_vector[offset] >= 0; + if (condition) break; + } + else break; + } + } + } + } + + /* Chose branch according to the condition */ + + ecode += condition? 1 + IMM2_SIZE : GET(ecode, 1); + } + + else if (condcode == OP_DEF) /* DEFINE - always false */ + { + condition = FALSE; + ecode += GET(ecode, 1); + } + + /* The condition is an assertion. Call match() to evaluate it - setting + md->match_function_type to MATCH_CONDASSERT causes it to stop at the end of + an assertion. */ + + else + { + md->match_function_type = MATCH_CONDASSERT; + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM3); + if (rrc == MATCH_MATCH) + { + if (md->end_offset_top > offset_top) + offset_top = md->end_offset_top; /* Captures may have happened */ + condition = TRUE; + ecode += 1 + LINK_SIZE + GET(ecode, LINK_SIZE + 2); + while (*ecode == OP_ALT) ecode += GET(ecode, 1); + } + + /* PCRE doesn't allow the effect of (*THEN) to escape beyond an + assertion; it is therefore treated as NOMATCH. */ + + else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) + { + RRETURN(rrc); /* Need braces because of following else */ + } + else + { + condition = FALSE; + ecode += codelink; + } + } + + /* We are now at the branch that is to be obeyed. As there is only one, can + use tail recursion to avoid using another stack frame, except when there is + unlimited repeat of a possibly empty group. In the latter case, a recursive + call to match() is always required, unless the second alternative doesn't + exist, in which case we can just plough on. Note that, for compatibility + with Perl, the | in a conditional group is NOT treated as creating two + alternatives. If a THEN is encountered in the branch, it propagates out to + the enclosing alternative (unless nested in a deeper set of alternatives, + of course). */ + + if (condition || *ecode == OP_ALT) + { + if (op != OP_SCOND) + { + ecode += 1 + LINK_SIZE; + goto TAIL_RECURSE; + } + + md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM49); + RRETURN(rrc); + } + + /* Condition false & no alternative; continue after the group. */ + + else + { + ecode += 1 + LINK_SIZE; + } + break; + + + /* Before OP_ACCEPT there may be any number of OP_CLOSE opcodes, + to close any currently open capturing brackets. */ + + case OP_CLOSE: + number = GET2(ecode, 1); + offset = number << 1; + +#ifdef PCRE_DEBUG + printf("end bracket %d at *ACCEPT", number); + printf("\n"); +#endif + + md->capture_last = number; + if (offset >= md->offset_max) md->offset_overflow = TRUE; else + { + md->offset_vector[offset] = + md->offset_vector[md->offset_end - number]; + md->offset_vector[offset+1] = (int)(eptr - md->start_subject); + if (offset_top <= offset) offset_top = offset + 2; + } + ecode += 1 + IMM2_SIZE; + break; + + + /* End of the pattern, either real or forced. */ + + case OP_END: + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + + /* If we have matched an empty string, fail if not in an assertion and not + in a recursion if either PCRE_NOTEMPTY is set, or if PCRE_NOTEMPTY_ATSTART + is set and we have matched at the start of the subject. In both cases, + backtracking will then try other alternatives, if any. */ + + if (eptr == mstart && op != OP_ASSERT_ACCEPT && + md->recursive == NULL && + (md->notempty || + (md->notempty_atstart && + mstart == md->start_subject + md->start_offset))) + RRETURN(MATCH_NOMATCH); + + /* Otherwise, we have a match. */ + + md->end_match_ptr = eptr; /* Record where we ended */ + md->end_offset_top = offset_top; /* and how many extracts were taken */ + md->start_match_ptr = mstart; /* and the start (\K can modify) */ + + /* For some reason, the macros don't work properly if an expression is + given as the argument to RRETURN when the heap is in use. */ + + rrc = (op == OP_END)? MATCH_MATCH : MATCH_ACCEPT; + RRETURN(rrc); + + /* Assertion brackets. Check the alternative branches in turn - the + matching won't pass the KET for an assertion. If any one branch matches, + the assertion is true. Lookbehind assertions have an OP_REVERSE item at the + start of each branch to move the current point backwards, so the code at + this level is identical to the lookahead case. When the assertion is part + of a condition, we want to return immediately afterwards. The caller of + this incarnation of the match() function will have set MATCH_CONDASSERT in + md->match_function type, and one of these opcodes will be the first opcode + that is processed. We use a local variable that is preserved over calls to + match() to remember this case. */ + + case OP_ASSERT: + case OP_ASSERTBACK: + save_mark = md->mark; + if (md->match_function_type == MATCH_CONDASSERT) + { + condassert = TRUE; + md->match_function_type = 0; + } + else condassert = FALSE; + + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM4); + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + { + mstart = md->start_match_ptr; /* In case \K reset it */ + break; + } + + /* PCRE does not allow THEN to escape beyond an assertion; it is treated + as NOMATCH. */ + + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode, 1); + md->mark = save_mark; + } + while (*ecode == OP_ALT); + + if (*ecode == OP_KET) RRETURN(MATCH_NOMATCH); + + /* If checking an assertion for a condition, return MATCH_MATCH. */ + + if (condassert) RRETURN(MATCH_MATCH); + + /* Continue from after the assertion, updating the offsets high water + mark, since extracts may have been taken during the assertion. */ + + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + ecode += 1 + LINK_SIZE; + offset_top = md->end_offset_top; + continue; + + /* Negative assertion: all branches must fail to match. Encountering SKIP, + PRUNE, or COMMIT means we must assume failure without checking subsequent + branches. */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK_NOT: + save_mark = md->mark; + if (md->match_function_type == MATCH_CONDASSERT) + { + condassert = TRUE; + md->match_function_type = 0; + } + else condassert = FALSE; + + do + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, NULL, RM5); + md->mark = save_mark; + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) RRETURN(MATCH_NOMATCH); + if (rrc == MATCH_SKIP || rrc == MATCH_PRUNE || rrc == MATCH_COMMIT) + { + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + } + + /* PCRE does not allow THEN to escape beyond an assertion; it is treated + as NOMATCH. */ + + if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) RRETURN(rrc); + ecode += GET(ecode,1); + } + while (*ecode == OP_ALT); + + if (condassert) RRETURN(MATCH_MATCH); /* Condition assertion */ + + ecode += 1 + LINK_SIZE; + continue; + + /* Move the subject pointer back. This occurs only at the start of + each branch of a lookbehind assertion. If we are too close to the start to + move back, this match function fails. When working with UTF-8 we move + back a number of characters, not bytes. */ + + case OP_REVERSE: +#ifdef SUPPORT_UTF + if (utf) + { + i = GET(ecode, 1); + while (i-- > 0) + { + eptr--; + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + BACKCHAR(eptr); + } + } + else +#endif + + /* No UTF-8 support, or not in UTF-8 mode: count is byte count */ + + { + eptr -= GET(ecode, 1); + if (eptr < md->start_subject) RRETURN(MATCH_NOMATCH); + } + + /* Save the earliest consulted character, then skip to next op code */ + + if (eptr < md->start_used_ptr) md->start_used_ptr = eptr; + ecode += 1 + LINK_SIZE; + break; + + /* The callout item calls an external function, if one is provided, passing + details of the match so far. This is mainly for debugging, though the + function is able to force a failure. */ + + case OP_CALLOUT: + if (PUBL(callout) != NULL) + { + PUBL(callout_block) cb; + cb.version = 2; /* Version 1 of the callout block */ + cb.callout_number = ecode[1]; + cb.offset_vector = md->offset_vector; +#ifdef COMPILE_PCRE8 + cb.subject = (PCRE_SPTR)md->start_subject; +#else + cb.subject = (PCRE_SPTR16)md->start_subject; +#endif + cb.subject_length = (int)(md->end_subject - md->start_subject); + cb.start_match = (int)(mstart - md->start_subject); + cb.current_position = (int)(eptr - md->start_subject); + cb.pattern_position = GET(ecode, 2); + cb.next_item_length = GET(ecode, 2 + LINK_SIZE); + cb.capture_top = offset_top/2; + cb.capture_last = md->capture_last; + cb.callout_data = md->callout_data; + cb.mark = md->nomatch_mark; + if ((rrc = (*PUBL(callout))(&cb)) > 0) RRETURN(MATCH_NOMATCH); + if (rrc < 0) RRETURN(rrc); + } + ecode += 2 + 2*LINK_SIZE; + break; + + /* Recursion either matches the current regex, or some subexpression. The + offset data is the offset to the starting bracket from the start of the + whole pattern. (This is so that it works from duplicated subpatterns.) + + The state of the capturing groups is preserved over recursion, and + re-instated afterwards. We don't know how many are started and not yet + finished (offset_top records the completed total) so we just have to save + all the potential data. There may be up to 65535 such values, which is too + large to put on the stack, but using malloc for small numbers seems + expensive. As a compromise, the stack is used when there are no more than + REC_STACK_SAVE_MAX values to store; otherwise malloc is used. + + There are also other values that have to be saved. We use a chained + sequence of blocks that actually live on the stack. Thanks to Robin Houston + for the original version of this logic. It has, however, been hacked around + a lot, so he is not to blame for the current way it works. */ + + case OP_RECURSE: + { + recursion_info *ri; + int recno; + + callpat = md->start_code + GET(ecode, 1); + recno = (callpat == md->start_code)? 0 : + GET2(callpat, 1 + LINK_SIZE); + + /* Check for repeating a recursion without advancing the subject pointer. + This should catch convoluted mutual recursions. (Some simple cases are + caught at compile time.) */ + + for (ri = md->recursive; ri != NULL; ri = ri->prevrec) + if (recno == ri->group_num && eptr == ri->subject_position) + RRETURN(PCRE_ERROR_RECURSELOOP); + + /* Add to "recursing stack" */ + + new_recursive.group_num = recno; + new_recursive.subject_position = eptr; + new_recursive.prevrec = md->recursive; + md->recursive = &new_recursive; + + /* Where to continue from afterwards */ + + ecode += 1 + LINK_SIZE; + + /* Now save the offset data */ + + new_recursive.saved_max = md->offset_end; + if (new_recursive.saved_max <= REC_STACK_SAVE_MAX) + new_recursive.offset_save = stacksave; + else + { + new_recursive.offset_save = + (int *)(PUBL(malloc))(new_recursive.saved_max * sizeof(int)); + if (new_recursive.offset_save == NULL) RRETURN(PCRE_ERROR_NOMEMORY); + } + memcpy(new_recursive.offset_save, md->offset_vector, + new_recursive.saved_max * sizeof(int)); + + /* OK, now we can do the recursion. After processing each alternative, + restore the offset data. If there were nested recursions, md->recursive + might be changed, so reset it before looping. */ + + DPRINTF(("Recursing into group %d\n", new_recursive.group_num)); + cbegroup = (*callpat >= OP_SBRA); + do + { + if (cbegroup) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, callpat + PRIV(OP_lengths)[*callpat], offset_top, + md, eptrb, RM6); + memcpy(md->offset_vector, new_recursive.offset_save, + new_recursive.saved_max * sizeof(int)); + md->recursive = new_recursive.prevrec; + if (rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) + { + DPRINTF(("Recursion matched\n")); + if (new_recursive.offset_save != stacksave) + (PUBL(free))(new_recursive.offset_save); + + /* Set where we got to in the subject, and reset the start in case + it was changed by \K. This *is* propagated back out of a recursion, + for Perl compatibility. */ + + eptr = md->end_match_ptr; + mstart = md->start_match_ptr; + goto RECURSION_MATCHED; /* Exit loop; end processing */ + } + + /* PCRE does not allow THEN to escape beyond a recursion; it is treated + as NOMATCH. */ + + else if (rrc != MATCH_NOMATCH && rrc != MATCH_THEN) + { + DPRINTF(("Recursion gave error %d\n", rrc)); + if (new_recursive.offset_save != stacksave) + (PUBL(free))(new_recursive.offset_save); + RRETURN(rrc); + } + + md->recursive = &new_recursive; + callpat += GET(callpat, 1); + } + while (*callpat == OP_ALT); + + DPRINTF(("Recursion didn't match\n")); + md->recursive = new_recursive.prevrec; + if (new_recursive.offset_save != stacksave) + (PUBL(free))(new_recursive.offset_save); + RRETURN(MATCH_NOMATCH); + } + + RECURSION_MATCHED: + break; + + /* An alternation is the end of a branch; scan along to find the end of the + bracketed group and go to there. */ + + case OP_ALT: + do ecode += GET(ecode,1); while (*ecode == OP_ALT); + break; + + /* BRAZERO, BRAMINZERO and SKIPZERO occur just before a bracket group, + indicating that it may occur zero times. It may repeat infinitely, or not + at all - i.e. it could be ()* or ()? or even (){0} in the pattern. Brackets + with fixed upper repeat limits are compiled as a number of copies, with the + optional ones preceded by BRAZERO or BRAMINZERO. */ + + case OP_BRAZERO: + next = ecode + 1; + RMATCH(eptr, next, offset_top, md, eptrb, RM10); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + do next += GET(next, 1); while (*next == OP_ALT); + ecode = next + 1 + LINK_SIZE; + break; + + case OP_BRAMINZERO: + next = ecode + 1; + do next += GET(next, 1); while (*next == OP_ALT); + RMATCH(eptr, next + 1+LINK_SIZE, offset_top, md, eptrb, RM11); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + ecode++; + break; + + case OP_SKIPZERO: + next = ecode+1; + do next += GET(next,1); while (*next == OP_ALT); + ecode = next + 1 + LINK_SIZE; + break; + + /* BRAPOSZERO occurs before a possessive bracket group. Don't do anything + here; just jump to the group, with allow_zero set TRUE. */ + + case OP_BRAPOSZERO: + op = *(++ecode); + allow_zero = TRUE; + if (op == OP_CBRAPOS || op == OP_SCBRAPOS) goto POSSESSIVE_CAPTURE; + goto POSSESSIVE_NON_CAPTURE; + + /* End of a group, repeated or non-repeating. */ + + case OP_KET: + case OP_KETRMIN: + case OP_KETRMAX: + case OP_KETRPOS: + prev = ecode - GET(ecode, 1); + + /* If this was a group that remembered the subject start, in order to break + infinite repeats of empty string matches, retrieve the subject start from + the chain. Otherwise, set it NULL. */ + + if (*prev >= OP_SBRA || *prev == OP_ONCE) + { + saved_eptr = eptrb->epb_saved_eptr; /* Value at start of group */ + eptrb = eptrb->epb_prev; /* Backup to previous group */ + } + else saved_eptr = NULL; + + /* If we are at the end of an assertion group or a non-capturing atomic + group, stop matching and return MATCH_MATCH, but record the current high + water mark for use by positive assertions. We also need to record the match + start in case it was changed by \K. */ + + if ((*prev >= OP_ASSERT && *prev <= OP_ASSERTBACK_NOT) || + *prev == OP_ONCE_NC) + { + md->end_match_ptr = eptr; /* For ONCE_NC */ + md->end_offset_top = offset_top; + md->start_match_ptr = mstart; + RRETURN(MATCH_MATCH); /* Sets md->mark */ + } + + /* For capturing groups we have to check the group number back at the start + and if necessary complete handling an extraction by setting the offsets and + bumping the high water mark. Whole-pattern recursion is coded as a recurse + into group 0, so it won't be picked up here. Instead, we catch it when the + OP_END is reached. Other recursion is handled here. We just have to record + the current subject position and start match pointer and give a MATCH + return. */ + + if (*prev == OP_CBRA || *prev == OP_SCBRA || + *prev == OP_CBRAPOS || *prev == OP_SCBRAPOS) + { + number = GET2(prev, 1+LINK_SIZE); + offset = number << 1; + +#ifdef PCRE_DEBUG + printf("end bracket %d", number); + printf("\n"); +#endif + + /* Handle a recursively called group. */ + + if (md->recursive != NULL && md->recursive->group_num == number) + { + md->end_match_ptr = eptr; + md->start_match_ptr = mstart; + RRETURN(MATCH_MATCH); + } + + /* Deal with capturing */ + + md->capture_last = number; + if (offset >= md->offset_max) md->offset_overflow = TRUE; else + { + /* If offset is greater than offset_top, it means that we are + "skipping" a capturing group, and that group's offsets must be marked + unset. In earlier versions of PCRE, all the offsets were unset at the + start of matching, but this doesn't work because atomic groups and + assertions can cause a value to be set that should later be unset. + Example: matching /(?>(a))b|(a)c/ against "ac". This sets group 1 as + part of the atomic group, but this is not on the final matching path, + so must be unset when 2 is set. (If there is no group 2, there is no + problem, because offset_top will then be 2, indicating no capture.) */ + + if (offset > offset_top) + { + register int *iptr = md->offset_vector + offset_top; + register int *iend = md->offset_vector + offset; + while (iptr < iend) *iptr++ = -1; + } + + /* Now make the extraction */ + + md->offset_vector[offset] = + md->offset_vector[md->offset_end - number]; + md->offset_vector[offset+1] = (int)(eptr - md->start_subject); + if (offset_top <= offset) offset_top = offset + 2; + } + } + + /* For an ordinary non-repeating ket, just continue at this level. This + also happens for a repeating ket if no characters were matched in the + group. This is the forcible breaking of infinite loops as implemented in + Perl 5.005. For a non-repeating atomic group that includes captures, + establish a backup point by processing the rest of the pattern at a lower + level. If this results in a NOMATCH return, pass MATCH_ONCE back to the + original OP_ONCE level, thereby bypassing intermediate backup points, but + resetting any captures that happened along the way. */ + + if (*ecode == OP_KET || eptr == saved_eptr) + { + if (*prev == OP_ONCE) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM12); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ + RRETURN(MATCH_ONCE); + } + ecode += 1 + LINK_SIZE; /* Carry on at this level */ + break; + } + + /* OP_KETRPOS is a possessive repeating ket. Remember the current position, + and return the MATCH_KETRPOS. This makes it possible to do the repeats one + at a time from the outer level, thus saving stack. */ + + if (*ecode == OP_KETRPOS) + { + md->end_match_ptr = eptr; + md->end_offset_top = offset_top; + RRETURN(MATCH_KETRPOS); + } + + /* The normal repeating kets try the rest of the pattern or restart from + the preceding bracket, in the appropriate order. In the second case, we can + use tail recursion to avoid using another stack frame, unless we have an + an atomic group or an unlimited repeat of a group that can match an empty + string. */ + + if (*ecode == OP_KETRMIN) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM7); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (*prev == OP_ONCE) + { + RMATCH(eptr, prev, offset_top, md, eptrb, RM8); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->once_target = prev; /* Level at which to change to MATCH_NOMATCH */ + RRETURN(MATCH_ONCE); + } + if (*prev >= OP_SBRA) /* Could match an empty string */ + { + md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, prev, offset_top, md, eptrb, RM50); + RRETURN(rrc); + } + ecode = prev; + goto TAIL_RECURSE; + } + else /* OP_KETRMAX */ + { + if (*prev >= OP_SBRA) md->match_function_type = MATCH_CBEGROUP; + RMATCH(eptr, prev, offset_top, md, eptrb, RM13); + if (rrc == MATCH_ONCE && md->once_target == prev) rrc = MATCH_NOMATCH; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (*prev == OP_ONCE) + { + RMATCH(eptr, ecode + 1 + LINK_SIZE, offset_top, md, eptrb, RM9); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + md->once_target = prev; + RRETURN(MATCH_ONCE); + } + ecode += 1 + LINK_SIZE; + goto TAIL_RECURSE; + } + /* Control never gets here */ + + /* Not multiline mode: start of subject assertion, unless notbol. */ + + case OP_CIRC: + if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); + + /* Start of subject assertion */ + + case OP_SOD: + if (eptr != md->start_subject) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Multiline mode: start of subject unless notbol, or after any newline. */ + + case OP_CIRCM: + if (md->notbol && eptr == md->start_subject) RRETURN(MATCH_NOMATCH); + if (eptr != md->start_subject && + (eptr == md->end_subject || !WAS_NEWLINE(eptr))) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Start of match assertion */ + + case OP_SOM: + if (eptr != md->start_subject + md->start_offset) RRETURN(MATCH_NOMATCH); + ecode++; + break; + + /* Reset the start of match point */ + + case OP_SET_SOM: + mstart = eptr; + ecode++; + break; + + /* Multiline mode: assert before any newline, or before end of subject + unless noteol is set. */ + + case OP_DOLLM: + if (eptr < md->end_subject) + { if (!IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); } + else + { + if (md->noteol) RRETURN(MATCH_NOMATCH); + SCHECK_PARTIAL(); + } + ecode++; + break; + + /* Not multiline mode: assert before a terminating newline or before end of + subject unless noteol is set. */ + + case OP_DOLL: + if (md->noteol) RRETURN(MATCH_NOMATCH); + if (!md->endonly) goto ASSERT_NL_OR_EOS; + + /* ... else fall through for endonly */ + + /* End of subject assertion (\z) */ + + case OP_EOD: + if (eptr < md->end_subject) RRETURN(MATCH_NOMATCH); + SCHECK_PARTIAL(); + ecode++; + break; + + /* End of subject or ending \n assertion (\Z) */ + + case OP_EODN: + ASSERT_NL_OR_EOS: + if (eptr < md->end_subject && + (!IS_NEWLINE(eptr) || eptr != md->end_subject - md->nllen)) + RRETURN(MATCH_NOMATCH); + + /* Either at end of string or \n before end. */ + + SCHECK_PARTIAL(); + ecode++; + break; + + /* Word boundary assertions */ + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + { + + /* Find out if the previous and current characters are "word" characters. + It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to + be "non-word" characters. Remember the earliest consulted character for + partial matching. */ + +#ifdef SUPPORT_UTF + if (utf) + { + /* Get status of previous character */ + + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + PCRE_PUCHAR lastptr = eptr - 1; + BACKCHAR(lastptr); + if (lastptr < md->start_used_ptr) md->start_used_ptr = lastptr; + GETCHAR(c, lastptr); +#ifdef SUPPORT_UCP + if (md->use_ucp) + { + if (c == '_') prev_is_word = TRUE; else + { + int cat = UCD_CATEGORY(c); + prev_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + prev_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + + /* Get status of next character */ + + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + cur_is_word = FALSE; + } + else + { + GETCHAR(c, eptr); +#ifdef SUPPORT_UCP + if (md->use_ucp) + { + if (c == '_') cur_is_word = TRUE; else + { + int cat = UCD_CATEGORY(c); + cur_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + cur_is_word = c < 256 && (md->ctypes[c] & ctype_word) != 0; + } + } + else +#endif + + /* Not in UTF-8 mode, but we may still have PCRE_UCP set, and for + consistency with the behaviour of \w we do use it in this case. */ + + { + /* Get status of previous character */ + + if (eptr == md->start_subject) prev_is_word = FALSE; else + { + if (eptr <= md->start_used_ptr) md->start_used_ptr = eptr - 1; +#ifdef SUPPORT_UCP + if (md->use_ucp) + { + c = eptr[-1]; + if (c == '_') prev_is_word = TRUE; else + { + int cat = UCD_CATEGORY(c); + prev_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + prev_is_word = MAX_255(eptr[-1]) + && ((md->ctypes[eptr[-1]] & ctype_word) != 0); + } + + /* Get status of next character */ + + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + cur_is_word = FALSE; + } + else +#ifdef SUPPORT_UCP + if (md->use_ucp) + { + c = *eptr; + if (c == '_') cur_is_word = TRUE; else + { + int cat = UCD_CATEGORY(c); + cur_is_word = (cat == ucp_L || cat == ucp_N); + } + } + else +#endif + cur_is_word = MAX_255(*eptr) + && ((md->ctypes[*eptr] & ctype_word) != 0); + } + + /* Now see if the situation is what we want */ + + if ((*ecode++ == OP_WORD_BOUNDARY)? + cur_is_word == prev_is_word : cur_is_word != prev_is_word) + RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a single character type; inline for speed */ + + case OP_ANY: + if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); + /* Fall through */ + + case OP_ALLANY: + if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ + { /* not be updated before SCHECK_PARTIAL. */ + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr++; +#ifdef SUPPORT_UTF + if (utf) ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); +#endif + ecode++; + break; + + /* Match a single byte, even in UTF-8 mode. This opcode really does match + any byte, even newline, independent of the setting of PCRE_DOTALL. */ + + case OP_ANYBYTE: + if (eptr >= md->end_subject) /* DO NOT merge the eptr++ here; it must */ + { /* not be updated before SCHECK_PARTIAL. */ + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr++; + ecode++; + break; + + case OP_NOT_DIGIT: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c < 256 && +#endif + (md->ctypes[c] & ctype_digit) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_DIGIT: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c > 255 || +#endif + (md->ctypes[c] & ctype_digit) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WHITESPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c < 256 && +#endif + (md->ctypes[c] & ctype_space) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WHITESPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c > 255 || +#endif + (md->ctypes[c] & ctype_space) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_NOT_WORDCHAR: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c < 256 && +#endif + (md->ctypes[c] & ctype_word) != 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_WORDCHAR: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ( +#if defined SUPPORT_UTF || !(defined COMPILE_PCRE8) + c > 255 || +#endif + (md->ctypes[c] & ctype_word) == 0 + ) + RRETURN(MATCH_NOMATCH); + ecode++; + break; + + case OP_ANYNL: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); + break; + } + ecode++; + break; + + case OP_NOT_HSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + RRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_HSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + break; + } + ecode++; + break; + + case OP_NOT_VSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + ecode++; + break; + + case OP_VSPACE: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + ecode++; + break; + +#ifdef SUPPORT_UCP + /* Check the next character by Unicode property. We will get here only + if the support is in the binary; otherwise a compile-time error occurs. */ + + case OP_PROP: + case OP_NOTPROP: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + { + const ucd_record *prop = GET_UCD(c); + + switch(ecode[1]) + { + case PT_ANY: + if (op == OP_NOTPROP) RRETURN(MATCH_NOMATCH); + break; + + case PT_LAMP: + if ((prop->chartype == ucp_Lu || + prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt) == (op == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_GC: + if ((ecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_PC: + if ((ecode[2] != prop->chartype) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_SC: + if ((ecode[2] != prop->script) == (op == OP_PROP)) + RRETURN(MATCH_NOMATCH); + break; + + /* These are specials */ + + case PT_ALNUM: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (op == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_SPACE: /* Perl space */ + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) + == (op == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_PXSPACE: /* POSIX space */ + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR) + == (op == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; + + case PT_WORD: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || + c == CHAR_UNDERSCORE) == (op == OP_NOTPROP)) + RRETURN(MATCH_NOMATCH); + break; + + /* This should never occur */ + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + ecode += 3; + } + break; + + /* Match an extended Unicode sequence. We will get here only if the support + is in the binary; otherwise a compile-time error occurs. */ + + case OP_EXTUNI: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + if (UCD_CATEGORY(c) != ucp_M) break; + eptr += len; + } + ecode++; + break; +#endif + + + /* Match a back reference, possibly repeatedly. Look past the end of the + item to see if there is repeat information following. The code is similar + to that for character classes, but repeated for efficiency. Then obey + similar code to character type repeats - written out again for speed. + However, if the referenced string is the empty string, always treat + it as matched, any number of times (otherwise there could be infinite + loops). */ + + case OP_REF: + case OP_REFI: + caseless = op == OP_REFI; + offset = GET2(ecode, 1) << 1; /* Doubled ref number */ + ecode += 1 + IMM2_SIZE; + + /* If the reference is unset, there are two possibilities: + + (a) In the default, Perl-compatible state, set the length negative; + this ensures that every attempt at a match fails. We can't just fail + here, because of the possibility of quantifiers with zero minima. + + (b) If the JavaScript compatibility flag is set, set the length to zero + so that the back reference matches an empty string. + + Otherwise, set the length to the length of what was matched by the + referenced subpattern. */ + + if (offset >= offset_top || md->offset_vector[offset] < 0) + length = (md->jscript_compat)? 0 : -1; + else + length = md->offset_vector[offset+1] - md->offset_vector[offset]; + + /* Set up for repetition, or handle the non-repeated case */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 1 + IMM2_SIZE); + if (max == 0) max = INT_MAX; + ecode += 1 + 2 * IMM2_SIZE; + break; + + default: /* No repeat follows */ + if ((length = match_ref(offset, eptr, length, md, caseless)) < 0) + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr += length; + continue; /* With the main loop */ + } + + /* Handle repeated back references. If the length of the reference is + zero, just continue with the main loop. If the length is negative, it + means the reference is unset in non-Java-compatible mode. If the minimum is + zero, we can continue at the same level without recursion. For any other + minimum, carrying on will result in NOMATCH. */ + + if (length == 0) continue; + if (length < 0 && min == 0) continue; + + /* First, ensure the minimum number of matches are present. We get back + the length of the reference string explicitly rather than passing the + address of eptr, so that eptr can be a register variable. */ + + for (i = 1; i <= min; i++) + { + int slength; + if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr += slength; + } + + /* If min = max, continue at the same level without recursion. + They are not both allowed to be zero. */ + + if (min == max) continue; + + /* If minimizing, keep trying and advancing the pointer */ + + if (minimize) + { + for (fi = min;; fi++) + { + int slength; + RMATCH(eptr, ecode, offset_top, md, eptrb, RM14); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr += slength; + } + /* Control never gets here */ + } + + /* If maximizing, find the longest string and work backwards */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + int slength; + if ((slength = match_ref(offset, eptr, length, md, caseless)) < 0) + { + CHECK_PARTIAL(); + break; + } + eptr += slength; + } + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM15); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr -= length; + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + /* Match a bit-mapped character class, possibly repeatedly. This op code is + used when all the characters in the class have values in the range 0-255, + and either the matching is caseful, or the characters are in the range + 0-127 when UTF-8 processing is enabled. The only difference between + OP_CLASS and OP_NCLASS occurs when a data character outside the range is + encountered. + + First, look past the end of the item to see if there is repeat information + following. Then obey similar code to character type repeats - written out + again for speed. */ + + case OP_NCLASS: + case OP_CLASS: + { + /* The data variable is saved across frames, so the byte map needs to + be stored there. */ +#define BYTE_MAP ((pcre_uint8 *)data) + data = ecode + 1; /* Save for matching */ + ecode += 1 + (32 / sizeof(pcre_uchar)); /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 1 + IMM2_SIZE); + if (max == 0) max = INT_MAX; + ecode += 1 + 2 * IMM2_SIZE; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + +#ifdef SUPPORT_UTF + if (utf) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + c = *eptr++; +#ifndef COMPILE_PCRE8 + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else +#endif + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { +#ifdef SUPPORT_UTF + if (utf) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM16); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM17); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + c = *eptr++; +#ifndef COMPILE_PCRE8 + if (c > 255) + { + if (op == OP_CLASS) RRETURN(MATCH_NOMATCH); + } + else +#endif + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF + if (utf) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c > 255) + { + if (op == OP_CLASS) break; + } + else + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; + eptr += len; + } + for (;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM18); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; +#ifndef COMPILE_PCRE8 + if (c > 255) + { + if (op == OP_CLASS) break; + } + else +#endif + if ((BYTE_MAP[c/8] & (1 << (c&7))) == 0) break; + eptr++; + } + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM19); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } +#undef BYTE_MAP + } + /* Control never gets here */ + + + /* Match an extended character class. This opcode is encountered only + when UTF-8 mode mode is supported. Nevertheless, we may not be in UTF-8 + mode, because Unicode properties are supported in non-UTF-8 mode. */ + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: + { + data = ecode + 1 + LINK_SIZE; /* Save for matching */ + ecode += GET(ecode, 1); /* Advance past the item */ + + switch (*ecode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + c = *ecode++ - OP_CRSTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + minimize = (*ecode == OP_CRMINRANGE); + min = GET2(ecode, 1); + max = GET2(ecode, 1 + IMM2_SIZE); + if (max == 0) max = INT_MAX; + ecode += 1 + 2 * IMM2_SIZE; + break; + + default: /* No repeat follows */ + min = max = 1; + break; + } + + /* First, ensure the minimum number of matches are present. */ + + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); + } + + /* If max == min we can continue with the main loop without the + need to recurse. */ + + if (min == max) continue; + + /* If minimizing, keep testing the rest of the expression and advancing + the pointer while it matches the class. */ + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM20); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (!PRIV(xclass)(c, data, utf)) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* If maximizing, find the longest possible run, then work backwards. */ + + else + { + pp = eptr; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } +#ifdef SUPPORT_UTF + GETCHARLENTEST(c, eptr, len); +#else + c = *eptr; +#endif + if (!PRIV(xclass)(c, data, utf)) break; + eptr += len; + } + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM21); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ +#ifdef SUPPORT_UTF + if (utf) BACKCHAR(eptr); +#endif + } + RRETURN(MATCH_NOMATCH); + } + + /* Control never gets here */ + } +#endif /* End of XCLASS */ + + /* Match a single character, casefully */ + + case OP_CHAR: +#ifdef SUPPORT_UTF + if (utf) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + if (length > md->end_subject - eptr) + { + CHECK_PARTIAL(); /* Not SCHECK_PARTIAL() */ + RRETURN(MATCH_NOMATCH); + } + while (length-- > 0) if (*ecode++ != *eptr++) RRETURN(MATCH_NOMATCH); + } + else +#endif + /* Not UTF mode */ + { + if (md->end_subject - eptr < 1) + { + SCHECK_PARTIAL(); /* This one can use SCHECK_PARTIAL() */ + RRETURN(MATCH_NOMATCH); + } + if (ecode[1] != *eptr++) RRETURN(MATCH_NOMATCH); + ecode += 2; + } + break; + + /* Match a single character, caselessly. If we are at the end of the + subject, give up immediately. */ + + case OP_CHARI: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + +#ifdef SUPPORT_UTF + if (utf) + { + length = 1; + ecode++; + GETCHARLEN(fc, ecode, length); + + /* If the pattern character's value is < 128, we have only one byte, and + we know that its other case must also be one byte long, so we can use the + fast lookup table. We know that there is at least one byte left in the + subject. */ + + if (fc < 128) + { + if (md->lcc[fc] + != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH); + ecode++; + eptr++; + } + + /* Otherwise we must pick up the subject character. Note that we cannot + use the value of "length" to check for sufficient bytes left, because the + other case of the character may have more or fewer bytes. */ + + else + { + unsigned int dc; + GETCHARINC(dc, eptr); + ecode += length; + + /* If we have Unicode property support, we can use it to test the other + case of the character, if there is one. */ + + if (fc != dc) + { +#ifdef SUPPORT_UCP + if (dc != UCD_OTHERCASE(fc)) +#endif + RRETURN(MATCH_NOMATCH); + } + } + } + else +#endif /* SUPPORT_UTF */ + + /* Not UTF mode */ + { + if (TABLE_GET(ecode[1], md->lcc, ecode[1]) + != TABLE_GET(*eptr, md->lcc, *eptr)) RRETURN(MATCH_NOMATCH); + eptr++; + ecode += 2; + } + break; + + /* Match a single character repeatedly. */ + + case OP_EXACT: + case OP_EXACTI: + min = max = GET2(ecode, 1); + ecode += 1 + IMM2_SIZE; + goto REPEATCHAR; + + case OP_POSUPTO: + case OP_POSUPTOI: + possessive = TRUE; + /* Fall through */ + + case OP_UPTO: + case OP_UPTOI: + case OP_MINUPTO: + case OP_MINUPTOI: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_MINUPTO || *ecode == OP_MINUPTOI; + ecode += 1 + IMM2_SIZE; + goto REPEATCHAR; + + case OP_POSSTAR: + case OP_POSSTARI: + possessive = TRUE; + min = 0; + max = INT_MAX; + ecode++; + goto REPEATCHAR; + + case OP_POSPLUS: + case OP_POSPLUSI: + possessive = TRUE; + min = 1; + max = INT_MAX; + ecode++; + goto REPEATCHAR; + + case OP_POSQUERY: + case OP_POSQUERYI: + possessive = TRUE; + min = 0; + max = 1; + ecode++; + goto REPEATCHAR; + + case OP_STAR: + case OP_STARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_PLUS: + case OP_PLUSI: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_QUERY: + case OP_QUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + c = *ecode++ - ((op < OP_STARI)? OP_STAR : OP_STARI); + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-character matches. */ + + REPEATCHAR: +#ifdef SUPPORT_UTF + if (utf) + { + length = 1; + charptr = ecode; + GETCHARLEN(fc, ecode, length); + ecode += length; + + /* Handle multibyte character matching specially here. There is + support for caseless matching if UCP support is present. */ + + if (length > 1) + { +#ifdef SUPPORT_UCP + unsigned int othercase; + if (op >= OP_STARI && /* Caseless */ + (othercase = UCD_OTHERCASE(fc)) != fc) + oclength = PRIV(ord2utf)(othercase, occhars); + else oclength = 0; +#endif /* SUPPORT_UCP */ + + for (i = 1; i <= min; i++) + { + if (eptr <= md->end_subject - length && + memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM22); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr <= md->end_subject - length && + memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + else /* Maximize */ + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr <= md->end_subject - length && + memcmp(eptr, charptr, IN_UCHARS(length)) == 0) eptr += length; +#ifdef SUPPORT_UCP + else if (oclength > 0 && + eptr <= md->end_subject - oclength && + memcmp(eptr, occhars, IN_UCHARS(oclength)) == 0) eptr += oclength; +#endif /* SUPPORT_UCP */ + else + { + CHECK_PARTIAL(); + break; + } + } + + if (possessive) continue; + + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM23); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr == pp) { RRETURN(MATCH_NOMATCH); } +#ifdef SUPPORT_UCP + eptr--; + BACKCHAR(eptr); +#else /* without SUPPORT_UCP */ + eptr -= length; +#endif /* SUPPORT_UCP */ + } + } + /* Control never gets here */ + } + + /* If the length of a UTF-8 character is 1, we fall through here, and + obey the code as for non-UTF-8 characters below, though in this case the + value of fc will always be < 128. */ + } + else +#endif /* SUPPORT_UTF */ + /* When not in UTF-8 mode, load a single-byte character. */ + fc = *ecode++; + + /* The value of fc at this point is always one character, though we may + or may not be in UTF mode. The code is duplicated for the caseless and + caseful cases, for speed, since matching characters is likely to be quite + common. First, ensure the minimum number of matches are present. If min = + max, continue at the same level without recursing. Otherwise, if + minimizing, keep trying the rest of the expression and advancing one + matching character if failing, up to the maximum. Alternatively, if + maximizing, find the maximum number of characters and work backwards. */ + + DPRINTF(("matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if (op >= OP_STARI) /* Caseless */ + { +#ifdef COMPILE_PCRE8 + /* fc must be < 128 if UTF is enabled. */ + foc = md->fcc[fc]; +#else +#ifdef SUPPORT_UTF +#ifdef SUPPORT_UCP + if (utf && fc > 127) + foc = UCD_OTHERCASE(fc); +#else + if (utf && fc > 127) + foc = fc; +#endif /* SUPPORT_UCP */ + else +#endif /* SUPPORT_UTF */ + foc = TABLE_GET(fc, md->fcc, fc); +#endif /* COMPILE_PCRE8 */ + + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH); + eptr++; + } + if (min == max) continue; + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM24); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc != *eptr && foc != *eptr) RRETURN(MATCH_NOMATCH); + eptr++; + } + /* Control never gets here */ + } + else /* Maximize */ + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (fc != *eptr && foc != *eptr) break; + eptr++; + } + + if (possessive) continue; + + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM25); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons (includes all multi-byte characters) */ + + else + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc != *eptr++) RRETURN(MATCH_NOMATCH); + } + + if (min == max) continue; + + if (minimize) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM26); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc != *eptr++) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + else /* Maximize */ + { + pp = eptr; + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (fc != *eptr) break; + eptr++; + } + if (possessive) continue; + + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM27); + eptr--; + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + } + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a negated single one-byte character. The character we are + checking can be multibyte. */ + + case OP_NOT: + case OP_NOTI: + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + ecode++; + GETCHARINCTEST(c, eptr); + if (op == OP_NOTI) /* The caseless case */ + { + register unsigned int ch, och; + ch = *ecode++; +#ifdef COMPILE_PCRE8 + /* ch must be < 128 if UTF is enabled. */ + och = md->fcc[ch]; +#else +#ifdef SUPPORT_UTF +#ifdef SUPPORT_UCP + if (utf && ch > 127) + och = UCD_OTHERCASE(ch); +#else + if (utf && ch > 127) + och = ch; +#endif /* SUPPORT_UCP */ + else +#endif /* SUPPORT_UTF */ + och = TABLE_GET(ch, md->fcc, ch); +#endif /* COMPILE_PCRE8 */ + if (ch == c || och == c) RRETURN(MATCH_NOMATCH); + } + else /* Caseful */ + { + if (*ecode++ == c) RRETURN(MATCH_NOMATCH); + } + break; + + /* Match a negated single one-byte character repeatedly. This is almost a + repeat of the code for a repeated single character, but I haven't found a + nice way of commoning these up that doesn't require a test of the + positive/negative option for each character match. Maybe that wouldn't add + very much to the time taken, but character matching *is* what this is all + about... */ + + case OP_NOTEXACT: + case OP_NOTEXACTI: + min = max = GET2(ecode, 1); + ecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; + + case OP_NOTUPTO: + case OP_NOTUPTOI: + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_NOTMINUPTO || *ecode == OP_NOTMINUPTOI; + ecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; + + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: + possessive = TRUE; + min = 0; + max = INT_MAX; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: + possessive = TRUE; + min = 1; + max = INT_MAX; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: + possessive = TRUE; + min = 0; + max = 1; + ecode++; + goto REPEATNOTCHAR; + + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: + possessive = TRUE; + min = 0; + max = GET2(ecode, 1); + ecode += 1 + IMM2_SIZE; + goto REPEATNOTCHAR; + + case OP_NOTSTAR: + case OP_NOTSTARI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: + case OP_NOTPLUS: + case OP_NOTPLUSI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: + case OP_NOTQUERY: + case OP_NOTQUERYI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: + c = *ecode++ - ((op >= OP_NOTSTARI)? OP_NOTSTARI: OP_NOTSTAR); + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single-byte matches. */ + + REPEATNOTCHAR: + fc = *ecode++; + + /* The code is duplicated for the caseless and caseful cases, for speed, + since matching characters is likely to be quite common. First, ensure the + minimum number of matches are present. If min = max, continue at the same + level without recursing. Otherwise, if minimizing, keep trying the rest of + the expression and advancing one matching character if failing, up to the + maximum. Alternatively, if maximizing, find the maximum number of + characters and work backwards. */ + + DPRINTF(("negative matching %c{%d,%d} against subject %.*s\n", fc, min, max, + max, eptr)); + + if (op >= OP_NOTSTARI) /* Caseless */ + { +#ifdef COMPILE_PCRE8 + /* fc must be < 128 if UTF is enabled. */ + foc = md->fcc[fc]; +#else +#ifdef SUPPORT_UTF +#ifdef SUPPORT_UCP + if (utf && fc > 127) + foc = UCD_OTHERCASE(fc); +#else + if (utf && fc > 127) + foc = fc; +#endif /* SUPPORT_UCP */ + else +#endif /* SUPPORT_UTF */ + foc = TABLE_GET(fc, md->fcc, fc); +#endif /* COMPILE_PCRE8 */ + +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d || (unsigned int) foc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); + eptr++; + } + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM28); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d || (unsigned int)foc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM29); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc == *eptr || foc == *eptr) RRETURN(MATCH_NOMATCH); + eptr++; + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(d, eptr, len); + if (fc == d || (unsigned int)foc == d) break; + eptr += len; + } + if (possessive) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM30); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (fc == *eptr || foc == *eptr) break; + eptr++; + } + if (possessive) continue; + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM31); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + } + + /* Caseful comparisons */ + + else + { +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc == *eptr++) RRETURN(MATCH_NOMATCH); + } + } + + if (min == max) continue; + + if (minimize) + { +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM32); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(d, eptr); + if (fc == d) RRETURN(MATCH_NOMATCH); + } + } + else +#endif + /* Not UTF mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM33); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (fc == *eptr++) RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + } + + /* Maximize case */ + + else + { + pp = eptr; + +#ifdef SUPPORT_UTF + if (utf) + { + register unsigned int d; + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(d, eptr, len); + if (fc == d) break; + eptr += len; + } + if (possessive) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM34); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + } + } + else +#endif + /* Not UTF mode */ + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (fc == *eptr) break; + eptr++; + } + if (possessive) continue; + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM35); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + } + } + + RRETURN(MATCH_NOMATCH); + } + } + /* Control never gets here */ + + /* Match a single character type repeatedly; several different opcodes + share code. This is very similar to the code for single characters, but we + repeat it in the interests of efficiency. */ + + case OP_TYPEEXACT: + min = max = GET2(ecode, 1); + minimize = TRUE; + ecode += 1 + IMM2_SIZE; + goto REPEATTYPE; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + min = 0; + max = GET2(ecode, 1); + minimize = *ecode == OP_TYPEMINUPTO; + ecode += 1 + IMM2_SIZE; + goto REPEATTYPE; + + case OP_TYPEPOSSTAR: + possessive = TRUE; + min = 0; + max = INT_MAX; + ecode++; + goto REPEATTYPE; + + case OP_TYPEPOSPLUS: + possessive = TRUE; + min = 1; + max = INT_MAX; + ecode++; + goto REPEATTYPE; + + case OP_TYPEPOSQUERY: + possessive = TRUE; + min = 0; + max = 1; + ecode++; + goto REPEATTYPE; + + case OP_TYPEPOSUPTO: + possessive = TRUE; + min = 0; + max = GET2(ecode, 1); + ecode += 1 + IMM2_SIZE; + goto REPEATTYPE; + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + c = *ecode++ - OP_TYPESTAR; + minimize = (c & 1) != 0; + min = rep_min[c]; /* Pick up values from tables; */ + max = rep_max[c]; /* zero for max => infinity */ + if (max == 0) max = INT_MAX; + + /* Common code for all repeated single character type matches. Note that + in UTF-8 mode, '.' matches a character of any length, but for the other + character types, the valid characters are all one-byte long. */ + + REPEATTYPE: + ctype = *ecode++; /* Code for the character type */ + +#ifdef SUPPORT_UCP + if (ctype == OP_PROP || ctype == OP_NOTPROP) + { + prop_fail_result = ctype == OP_NOTPROP; + prop_type = *ecode++; + prop_value = *ecode++; + } + else prop_type = -1; +#endif + + /* First, ensure the minimum number of matches are present. Use inline + code for maximizing the speed, and do the type test once at the start + (i.e. keep it out of the loop). Separate the UTF-8 code completely as that + is tidier. Also separate the UCP code, which can be the same for both UTF-8 + and single-bytes. */ + + if (min > 0) + { +#ifdef SUPPORT_UCP + if (prop_type >= 0) + { + switch(prop_type) + { + case PT_ANY: + if (prop_fail_result) RRETURN(MATCH_NOMATCH); + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + } + break; + + case PT_LAMP: + for (i = 1; i <= min; i++) + { + int chartype; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + chartype = UCD_CHARTYPE(c); + if ((chartype == ucp_Lu || + chartype == ucp_Ll || + chartype == ucp_Lt) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_GC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_PC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_SC: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_ALNUM: + for (i = 1; i <= min; i++) + { + int category; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + category = UCD_CATEGORY(c); + if ((category == ucp_L || category == ucp_N) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_SPACE: /* Perl space */ + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_PXSPACE: /* POSIX space */ + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + case PT_WORD: + for (i = 1; i <= min; i++) + { + int category; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + category = UCD_CATEGORY(c); + if ((category == ucp_L || category == ucp_N || c == CHAR_UNDERSCORE) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + break; + + /* This should not occur */ + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + if (UCD_CATEGORY(c) != ucp_M) break; + eptr += len; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +/* Handle all other cases when the coding is UTF-8 */ + +#ifdef SUPPORT_UTF + if (utf) switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + break; + + case OP_ALLANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + break; + + case OP_ANYBYTE: + if (eptr > md->end_subject - min) RRETURN(MATCH_NOMATCH); + eptr += min; + break; + + case OP_ANYNL: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); + break; + } + } + break; + + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + break; + } + } + break; + + case OP_NOT_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + } + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINC(c, eptr); + if (c < 128 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (*eptr < 128 && (md->ctypes[*eptr] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (*eptr < 128 && (md->ctypes[*eptr] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (*eptr >= 128 || (md->ctypes[*eptr] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + /* No need to skip more bytes - we know it's a 1-byte character */ + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } /* End switch(ctype) */ + + else +#endif /* SUPPORT_UTF */ + + /* Code for the non-UTF-8 case for minimum matching of operators other + than OP_PROP and OP_NOTPROP. */ + + switch(ctype) + { + case OP_ANY: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (IS_NEWLINE(eptr)) RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_ALLANY: + if (eptr > md->end_subject - min) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr += min; + break; + + case OP_ANYBYTE: + if (eptr > md->end_subject - min) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + eptr += min; + break; + + case OP_ANYNL: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: RRETURN(MATCH_NOMATCH); + + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: +#ifdef COMPILE_PCRE16 + case 0x2028: + case 0x2029: +#endif + if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); + break; + } + } + break; + + case OP_NOT_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ +#ifdef COMPILE_PCRE16 + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ +#endif + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_HSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ +#ifdef COMPILE_PCRE16 + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ +#endif + break; + } + } + break; + + case OP_NOT_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ +#ifdef COMPILE_PCRE16 + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ +#endif + RRETURN(MATCH_NOMATCH); + } + } + break; + + case OP_VSPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + switch(*eptr++) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ +#ifdef COMPILE_PCRE16 + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ +#endif + break; + } + } + break; + + case OP_NOT_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_DIGIT: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_NOT_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_WHITESPACE: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_NOT_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + case OP_WORDCHAR: + for (i = 1; i <= min; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + eptr++; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + + /* If min = max, continue at the same level without recursing */ + + if (min == max) continue; + + /* If minimizing, we have to test the rest of the pattern before each + subsequent match. Again, separate the UTF-8 case for speed, and also + separate the UCP cases. */ + + if (minimize) + { +#ifdef SUPPORT_UCP + if (prop_type >= 0) + { + switch(prop_type) + { + case PT_ANY: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM36); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (prop_fail_result) RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_LAMP: + for (fi = min;; fi++) + { + int chartype; + RMATCH(eptr, ecode, offset_top, md, eptrb, RM37); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + chartype = UCD_CHARTYPE(c); + if ((chartype == ucp_Lu || + chartype == ucp_Ll || + chartype == ucp_Lt) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_GC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM38); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_PC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM39); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_SC: + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM40); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_ALNUM: + for (fi = min;; fi++) + { + int category; + RMATCH(eptr, ecode, offset_top, md, eptrb, RM59); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + category = UCD_CATEGORY(c); + if ((category == ucp_L || category == ucp_N) == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_SPACE: /* Perl space */ + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM60); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_PXSPACE: /* POSIX space */ + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM61); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + case PT_WORD: + for (fi = min;; fi++) + { + int category; + RMATCH(eptr, ecode, offset_top, md, eptrb, RM62); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + category = UCD_CATEGORY(c); + if ((category == ucp_L || + category == ucp_N || + c == CHAR_UNDERSCORE) + == prop_fail_result) + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + /* This should never occur */ + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM41); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + GETCHARINCTEST(c, eptr); + if (UCD_CATEGORY(c) == ucp_M) RRETURN(MATCH_NOMATCH); + while (eptr < md->end_subject) + { + int len = 1; + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + if (UCD_CATEGORY(c) != ucp_M) break; + eptr += len; + } + } + } + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF + if (utf) + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM42); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (ctype == OP_ANY && IS_NEWLINE(eptr)) + RRETURN(MATCH_NOMATCH); + GETCHARINC(c, eptr); + switch(ctype) + { + case OP_ANY: /* This is the non-NL case */ + case OP_ALLANY: + case OP_ANYBYTE: + break; + + case OP_ANYNL: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: + case 0x2028: + case 0x2029: + if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); + break; + } + break; + + case OP_NOT_HSPACE: + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + break; + } + break; + + case OP_NOT_VSPACE: + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + break; + } + break; + + case OP_NOT_DIGIT: + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if (c >= 256 || (md->ctypes[c] & ctype_digit) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if (c >= 256 || (md->ctypes[c] & ctype_space) == 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) + RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) + RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + else +#endif + /* Not UTF mode */ + { + for (fi = min;; fi++) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM43); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (fi >= max) RRETURN(MATCH_NOMATCH); + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + RRETURN(MATCH_NOMATCH); + } + if (ctype == OP_ANY && IS_NEWLINE(eptr)) + RRETURN(MATCH_NOMATCH); + c = *eptr++; + switch(ctype) + { + case OP_ANY: /* This is the non-NL case */ + case OP_ALLANY: + case OP_ANYBYTE: + break; + + case OP_ANYNL: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x000d: + if (eptr < md->end_subject && *eptr == 0x0a) eptr++; + break; + + case 0x000a: + break; + + case 0x000b: + case 0x000c: + case 0x0085: +#ifdef COMPILE_PCRE16 + case 0x2028: + case 0x2029: +#endif + if (md->bsr_anycrlf) RRETURN(MATCH_NOMATCH); + break; + } + break; + + case OP_NOT_HSPACE: + switch(c) + { + default: break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ +#ifdef COMPILE_PCRE16 + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ +#endif + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_HSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ +#ifdef COMPILE_PCRE16 + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ +#endif + break; + } + break; + + case OP_NOT_VSPACE: + switch(c) + { + default: break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ +#ifdef COMPILE_PCRE16 + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ +#endif + RRETURN(MATCH_NOMATCH); + } + break; + + case OP_VSPACE: + switch(c) + { + default: RRETURN(MATCH_NOMATCH); + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ +#ifdef COMPILE_PCRE16 + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ +#endif + break; + } + break; + + case OP_NOT_DIGIT: + if (MAX_255(c) && (md->ctypes[c] & ctype_digit) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_DIGIT: + if (!MAX_255(c) || (md->ctypes[c] & ctype_digit) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WHITESPACE: + if (MAX_255(c) && (md->ctypes[c] & ctype_space) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WHITESPACE: + if (!MAX_255(c) || (md->ctypes[c] & ctype_space) == 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_NOT_WORDCHAR: + if (MAX_255(c) && (md->ctypes[c] & ctype_word) != 0) RRETURN(MATCH_NOMATCH); + break; + + case OP_WORDCHAR: + if (!MAX_255(c) || (md->ctypes[c] & ctype_word) == 0) RRETURN(MATCH_NOMATCH); + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + } + } + /* Control never gets here */ + } + + /* If maximizing, it is worth using inline code for speed, doing the type + test once at the start (i.e. keep it out of the loop). Again, keep the + UTF-8 and UCP stuff separate. */ + + else + { + pp = eptr; /* Remember where we started */ + +#ifdef SUPPORT_UCP + if (prop_type >= 0) + { + switch(prop_type) + { + case PT_ANY: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if (prop_fail_result) break; + eptr+= len; + } + break; + + case PT_LAMP: + for (i = min; i < max; i++) + { + int chartype; + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + chartype = UCD_CHARTYPE(c); + if ((chartype == ucp_Lu || + chartype == ucp_Ll || + chartype == ucp_Lt) == prop_fail_result) + break; + eptr+= len; + } + break; + + case PT_GC: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if ((UCD_CATEGORY(c) == prop_value) == prop_fail_result) break; + eptr+= len; + } + break; + + case PT_PC: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if ((UCD_CHARTYPE(c) == prop_value) == prop_fail_result) break; + eptr+= len; + } + break; + + case PT_SC: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if ((UCD_SCRIPT(c) == prop_value) == prop_fail_result) break; + eptr+= len; + } + break; + + case PT_ALNUM: + for (i = min; i < max; i++) + { + int category; + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + category = UCD_CATEGORY(c); + if ((category == ucp_L || category == ucp_N) == prop_fail_result) + break; + eptr+= len; + } + break; + + case PT_SPACE: /* Perl space */ + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + break; + eptr+= len; + } + break; + + case PT_PXSPACE: /* POSIX space */ + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + if ((UCD_CATEGORY(c) == ucp_Z || c == CHAR_HT || c == CHAR_NL || + c == CHAR_VT || c == CHAR_FF || c == CHAR_CR) + == prop_fail_result) + break; + eptr+= len; + } + break; + + case PT_WORD: + for (i = min; i < max; i++) + { + int category; + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLENTEST(c, eptr, len); + category = UCD_CATEGORY(c); + if ((category == ucp_L || category == ucp_N || + c == CHAR_UNDERSCORE) == prop_fail_result) + break; + eptr+= len; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run */ + + if (possessive) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM44); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + if (utf) BACKCHAR(eptr); + } + } + + /* Match extended Unicode sequences. We will get here only if the + support is in the binary; otherwise a compile-time error occurs. */ + + else if (ctype == OP_EXTUNI) + { + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + if (UCD_CATEGORY(c) == ucp_M) break; + eptr += len; + while (eptr < md->end_subject) + { + len = 1; + if (!utf) c = *eptr; else { GETCHARLEN(c, eptr, len); } + if (UCD_CATEGORY(c) != ucp_M) break; + eptr += len; + } + } + + /* eptr is now past the end of the maximum run */ + + if (possessive) continue; + + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM45); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + for (;;) /* Move back over one extended */ + { + if (!utf) c = *eptr; else + { + BACKCHAR(eptr); + GETCHAR(c, eptr); + } + if (UCD_CATEGORY(c) != ucp_M) break; + eptr--; + } + } + } + + else +#endif /* SUPPORT_UCP */ + +#ifdef SUPPORT_UTF + if (utf) + { + switch(ctype) + { + case OP_ANY: + if (max < INT_MAX) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (IS_NEWLINE(eptr)) break; + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + } + + /* Handle unlimited UTF-8 repeat */ + + else + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (IS_NEWLINE(eptr)) break; + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + } + break; + + case OP_ALLANY: + if (max < INT_MAX) + { + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + eptr++; + ACROSSCHAR(eptr < md->end_subject, *eptr, eptr++); + } + } + else + { + eptr = md->end_subject; /* Unlimited UTF-8 repeat */ + SCHECK_PARTIAL(); + } + break; + + /* The byte case is the same as non-UTF8 */ + + case OP_ANYBYTE: + c = max - min; + if (c > (unsigned int)(md->end_subject - eptr)) + { + eptr = md->end_subject; + SCHECK_PARTIAL(); + } + else eptr += c; + break; + + case OP_ANYNL: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c == 0x000d) + { + if (++eptr >= md->end_subject) break; + if (*eptr == 0x000a) eptr++; + } + else + { + if (c != 0x000a && + (md->bsr_anycrlf || + (c != 0x000b && c != 0x000c && + c != 0x0085 && c != 0x2028 && c != 0x2029))) + break; + eptr += len; + } + } + break; + + case OP_NOT_HSPACE: + case OP_HSPACE: + for (i = min; i < max; i++) + { + BOOL gotspace; + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + switch(c) + { + default: gotspace = FALSE; break; + case 0x09: /* HT */ + case 0x20: /* SPACE */ + case 0xa0: /* NBSP */ + case 0x1680: /* OGHAM SPACE MARK */ + case 0x180e: /* MONGOLIAN VOWEL SEPARATOR */ + case 0x2000: /* EN QUAD */ + case 0x2001: /* EM QUAD */ + case 0x2002: /* EN SPACE */ + case 0x2003: /* EM SPACE */ + case 0x2004: /* THREE-PER-EM SPACE */ + case 0x2005: /* FOUR-PER-EM SPACE */ + case 0x2006: /* SIX-PER-EM SPACE */ + case 0x2007: /* FIGURE SPACE */ + case 0x2008: /* PUNCTUATION SPACE */ + case 0x2009: /* THIN SPACE */ + case 0x200A: /* HAIR SPACE */ + case 0x202f: /* NARROW NO-BREAK SPACE */ + case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ + case 0x3000: /* IDEOGRAPHIC SPACE */ + gotspace = TRUE; + break; + } + if (gotspace == (ctype == OP_NOT_HSPACE)) break; + eptr += len; + } + break; + + case OP_NOT_VSPACE: + case OP_VSPACE: + for (i = min; i < max; i++) + { + BOOL gotspace; + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + switch(c) + { + default: gotspace = FALSE; break; + case 0x0a: /* LF */ + case 0x0b: /* VT */ + case 0x0c: /* FF */ + case 0x0d: /* CR */ + case 0x85: /* NEL */ + case 0x2028: /* LINE SEPARATOR */ + case 0x2029: /* PARAGRAPH SEPARATOR */ + gotspace = TRUE; + break; + } + if (gotspace == (ctype == OP_NOT_VSPACE)) break; + eptr += len; + } + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_digit) != 0) break; + eptr+= len; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_digit) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_space) != 0) break; + eptr+= len; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c >= 256 ||(md->ctypes[c] & ctype_space) == 0) break; + eptr+= len; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c < 256 && (md->ctypes[c] & ctype_word) != 0) break; + eptr+= len; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + int len = 1; + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + GETCHARLEN(c, eptr, len); + if (c >= 256 || (md->ctypes[c] & ctype_word) == 0) break; + eptr+= len; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run. If possessive, we are + done (no backing up). Otherwise, match at this position; anything other + than no match is immediately returned. For nomatch, back up one + character, unless we are matching \R and the last thing matched was + \r\n, in which case, back up two bytes. */ + + if (possessive) continue; + for(;;) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM46); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + if (eptr-- == pp) break; /* Stop if tried at original pos */ + BACKCHAR(eptr); + if (ctype == OP_ANYNL && eptr > pp && *eptr == '\n' && + eptr[-1] == '\r') eptr--; + } + } + else +#endif /* SUPPORT_UTF */ + /* Not UTF mode */ + { + switch(ctype) + { + case OP_ANY: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (IS_NEWLINE(eptr)) break; + eptr++; + } + break; + + case OP_ALLANY: + case OP_ANYBYTE: + c = max - min; + if (c > (unsigned int)(md->end_subject - eptr)) + { + eptr = md->end_subject; + SCHECK_PARTIAL(); + } + else eptr += c; + break; + + case OP_ANYNL: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if (c == 0x000d) + { + if (++eptr >= md->end_subject) break; + if (*eptr == 0x000a) eptr++; + } + else + { + if (c != 0x000a && (md->bsr_anycrlf || + (c != 0x000b && c != 0x000c && c != 0x0085 +#ifdef COMPILE_PCRE16 + && c != 0x2028 && c != 0x2029 +#endif + ))) break; + eptr++; + } + } + break; + + case OP_NOT_HSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if (c == 0x09 || c == 0x20 || c == 0xa0 +#ifdef COMPILE_PCRE16 + || c == 0x1680 || c == 0x180e || (c >= 0x2000 && c <= 0x200A) + || c == 0x202f || c == 0x205f || c == 0x3000 +#endif + ) break; + eptr++; + } + break; + + case OP_HSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if (c != 0x09 && c != 0x20 && c != 0xa0 +#ifdef COMPILE_PCRE16 + && c != 0x1680 && c != 0x180e && (c < 0x2000 || c > 0x200A) + && c != 0x202f && c != 0x205f && c != 0x3000 +#endif + ) break; + eptr++; + } + break; + + case OP_NOT_VSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if (c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d || c == 0x85 +#ifdef COMPILE_PCRE16 + || c == 0x2028 || c == 0x2029 +#endif + ) break; + eptr++; + } + break; + + case OP_VSPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + c = *eptr; + if (c != 0x0a && c != 0x0b && c != 0x0c && c != 0x0d && c != 0x85 +#ifdef COMPILE_PCRE16 + && c != 0x2028 && c != 0x2029 +#endif + ) break; + eptr++; + } + break; + + case OP_NOT_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_digit) != 0) break; + eptr++; + } + break; + + case OP_DIGIT: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_digit) == 0) break; + eptr++; + } + break; + + case OP_NOT_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_space) != 0) break; + eptr++; + } + break; + + case OP_WHITESPACE: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_space) == 0) break; + eptr++; + } + break; + + case OP_NOT_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (MAX_255(*eptr) && (md->ctypes[*eptr] & ctype_word) != 0) break; + eptr++; + } + break; + + case OP_WORDCHAR: + for (i = min; i < max; i++) + { + if (eptr >= md->end_subject) + { + SCHECK_PARTIAL(); + break; + } + if (!MAX_255(*eptr) || (md->ctypes[*eptr] & ctype_word) == 0) break; + eptr++; + } + break; + + default: + RRETURN(PCRE_ERROR_INTERNAL); + } + + /* eptr is now past the end of the maximum run. If possessive, we are + done (no backing up). Otherwise, match at this position; anything other + than no match is immediately returned. For nomatch, back up one + character (byte), unless we are matching \R and the last thing matched + was \r\n, in which case, back up two bytes. */ + + if (possessive) continue; + while (eptr >= pp) + { + RMATCH(eptr, ecode, offset_top, md, eptrb, RM47); + if (rrc != MATCH_NOMATCH) RRETURN(rrc); + eptr--; + if (ctype == OP_ANYNL && eptr > pp && *eptr == '\n' && + eptr[-1] == '\r') eptr--; + } + } + + /* Get here if we can't make it match with any permitted repetitions */ + + RRETURN(MATCH_NOMATCH); + } + /* Control never gets here */ + + /* There's been some horrible disaster. Arrival here can only mean there is + something seriously wrong in the code above or the OP_xxx definitions. */ + + default: + DPRINTF(("Unknown opcode %d\n", *ecode)); + RRETURN(PCRE_ERROR_UNKNOWN_OPCODE); + } + + /* Do not stick any code in here without much thought; it is assumed + that "continue" in the code above comes out to here to repeat the main + loop. */ + + } /* End of main loop */ +/* Control never reaches here */ + + +/* When compiling to use the heap rather than the stack for recursive calls to +match(), the RRETURN() macro jumps here. The number that is saved in +frame->Xwhere indicates which label we actually want to return to. */ + +#ifdef NO_RECURSE +#define LBL(val) case val: goto L_RM##val; +HEAP_RETURN: +switch (frame->Xwhere) + { + LBL( 1) LBL( 2) LBL( 3) LBL( 4) LBL( 5) LBL( 6) LBL( 7) LBL( 8) + LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(17) + LBL(19) LBL(24) LBL(25) LBL(26) LBL(27) LBL(29) LBL(31) LBL(33) + LBL(35) LBL(43) LBL(47) LBL(48) LBL(49) LBL(50) LBL(51) LBL(52) + LBL(53) LBL(54) LBL(55) LBL(56) LBL(57) LBL(58) LBL(63) LBL(64) + LBL(65) LBL(66) +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + LBL(21) +#endif +#ifdef SUPPORT_UTF + LBL(16) LBL(18) LBL(20) + LBL(22) LBL(23) LBL(28) LBL(30) + LBL(32) LBL(34) LBL(42) LBL(46) +#ifdef SUPPORT_UCP + LBL(36) LBL(37) LBL(38) LBL(39) LBL(40) LBL(41) LBL(44) LBL(45) + LBL(59) LBL(60) LBL(61) LBL(62) +#endif /* SUPPORT_UCP */ +#endif /* SUPPORT_UTF */ + default: + DPRINTF(("jump error in pcre match: label %d non-existent\n", frame->Xwhere)); + +printf("+++jump error in pcre match: label %d non-existent\n", frame->Xwhere); + + return PCRE_ERROR_INTERNAL; + } +#undef LBL +#endif /* NO_RECURSE */ +} + + +/*************************************************************************** +**************************************************************************** + RECURSION IN THE match() FUNCTION + +Undefine all the macros that were defined above to handle this. */ + +#ifdef NO_RECURSE +#undef eptr +#undef ecode +#undef mstart +#undef offset_top +#undef eptrb +#undef flags + +#undef callpat +#undef charptr +#undef data +#undef next +#undef pp +#undef prev +#undef saved_eptr + +#undef new_recursive + +#undef cur_is_word +#undef condition +#undef prev_is_word + +#undef ctype +#undef length +#undef max +#undef min +#undef number +#undef offset +#undef op +#undef save_capture_last +#undef save_offset1 +#undef save_offset2 +#undef save_offset3 +#undef stacksave + +#undef newptrb + +#endif + +/* These two are defined as macros in both cases */ + +#undef fc +#undef fi + +/*************************************************************************** +***************************************************************************/ + + + +/************************************************* +* Execute a Regular Expression * +*************************************************/ + +/* This function applies a compiled re to a subject string and picks out +portions of the string if it matches. Two elements in the vector are set for +each substring: the offsets to the start and end of the substring. + +Arguments: + argument_re points to the compiled expression + extra_data points to extra data or is NULL + subject points to the subject string + length length of subject string (may contain binary zeros) + start_offset where to start in the subject string + options option bits + offsets points to a vector of ints to be filled in with offsets + offsetcount the number of elements in the vector + +Returns: > 0 => success; value is the number of elements filled in + = 0 => success, but offsets is not big enough + -1 => failed to match + < -1 => some kind of unexpected problem +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_exec(const pcre *argument_re, const pcre_extra *extra_data, + PCRE_SPTR subject, int length, int start_offset, int options, int *offsets, + int offsetcount) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_exec(const pcre16 *argument_re, const pcre16_extra *extra_data, + PCRE_SPTR16 subject, int length, int start_offset, int options, int *offsets, + int offsetcount) +#endif +{ +int rc, ocount, arg_offset_max; +int newline; +BOOL using_temporary_offsets = FALSE; +BOOL anchored; +BOOL startline; +BOOL firstline; +BOOL utf; +BOOL has_first_char = FALSE; +BOOL has_req_char = FALSE; +pcre_uchar first_char = 0; +pcre_uchar first_char2 = 0; +pcre_uchar req_char = 0; +pcre_uchar req_char2 = 0; +match_data match_block; +match_data *md = &match_block; +const pcre_uint8 *tables; +const pcre_uint8 *start_bits = NULL; +PCRE_PUCHAR start_match = (PCRE_PUCHAR)subject + start_offset; +PCRE_PUCHAR end_subject; +PCRE_PUCHAR start_partial = NULL; +PCRE_PUCHAR req_char_ptr = start_match - 1; + +const pcre_study_data *study; +const REAL_PCRE *re = (const REAL_PCRE *)argument_re; + +/* Check for the special magic call that measures the size of the stack used +per recursive call of match(). */ + +if (re == NULL && extra_data == NULL && subject == NULL && length == -999 && + start_offset == -999) +#ifdef NO_RECURSE + return -sizeof(heapframe); +#else + return match(NULL, NULL, NULL, 0, NULL, NULL, 0); +#endif + +/* Plausibility checks */ + +if ((options & ~PUBLIC_EXEC_OPTIONS) != 0) return PCRE_ERROR_BADOPTION; +if (re == NULL || subject == NULL || (offsets == NULL && offsetcount > 0)) + return PCRE_ERROR_NULL; +if (offsetcount < 0) return PCRE_ERROR_BADCOUNT; +if (start_offset < 0 || start_offset > length) return PCRE_ERROR_BADOFFSET; + +/* Check that the first field in the block is the magic number. If it is not, +return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to +REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which +means that the pattern is likely compiled with different endianness. */ + +if (re->magic_number != MAGIC_NUMBER) + return re->magic_number == REVERSED_MAGIC_NUMBER? + PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; +if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; + +/* These two settings are used in the code for checking a UTF-8 string that +follows immediately afterwards. Other values in the md block are used only +during "normal" pcre_exec() processing, not when the JIT support is in use, +so they are set up later. */ + +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +utf = md->utf = (re->options & PCRE_UTF8) != 0; +md->partial = ((options & PCRE_PARTIAL_HARD) != 0)? 2 : + ((options & PCRE_PARTIAL_SOFT) != 0)? 1 : 0; + +/* Check a UTF-8 string if required. Pass back the character offset and error +code for an invalid string if a results vector is available. */ + +#ifdef SUPPORT_UTF +if (utf && (options & PCRE_NO_UTF8_CHECK) == 0) + { + int erroroffset; + int errorcode = PRIV(valid_utf)((PCRE_PUCHAR)subject, length, &erroroffset); + if (errorcode != 0) + { + if (offsetcount >= 2) + { + offsets[0] = erroroffset; + offsets[1] = errorcode; + } +#ifdef COMPILE_PCRE16 + return (errorcode <= PCRE_UTF16_ERR1 && md->partial > 1)? + PCRE_ERROR_SHORTUTF16 : PCRE_ERROR_BADUTF16; +#else + return (errorcode <= PCRE_UTF8_ERR5 && md->partial > 1)? + PCRE_ERROR_SHORTUTF8 : PCRE_ERROR_BADUTF8; +#endif + } + + /* Check that a start_offset points to the start of a UTF character. */ + if (start_offset > 0 && start_offset < length && + NOT_FIRSTCHAR(((PCRE_PUCHAR)subject)[start_offset])) + return PCRE_ERROR_BADUTF8_OFFSET; + } +#endif + +/* If the pattern was successfully studied with JIT support, run the JIT +executable instead of the rest of this function. Most options must be set at +compile time for the JIT code to be usable. Fallback to the normal code path if +an unsupported flag is set. In particular, JIT does not support partial +matching. */ + +#ifdef SUPPORT_JIT +if (extra_data != NULL + && (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 + && extra_data->executable_jit != NULL + && (extra_data->flags & PCRE_EXTRA_TABLES) == 0 + && (options & ~(PCRE_NO_UTF8_CHECK | PCRE_NOTBOL | PCRE_NOTEOL | + PCRE_NOTEMPTY | PCRE_NOTEMPTY_ATSTART)) == 0) + return PRIV(jit_exec)(re, extra_data->executable_jit, + (const pcre_uchar *)subject, length, start_offset, options, + ((extra_data->flags & PCRE_EXTRA_MATCH_LIMIT) == 0) + ? MATCH_LIMIT : extra_data->match_limit, offsets, offsetcount); +#endif + +/* Carry on with non-JIT matching. This information is for finding all the +numbers associated with a given name, for condition testing. */ + +md->name_table = (pcre_uchar *)re + re->name_table_offset; +md->name_count = re->name_count; +md->name_entry_size = re->name_entry_size; + +/* Fish out the optional data from the extra_data structure, first setting +the default values. */ + +study = NULL; +md->match_limit = MATCH_LIMIT; +md->match_limit_recursion = MATCH_LIMIT_RECURSION; +md->callout_data = NULL; + +/* The table pointer is always in native byte order. */ + +tables = re->tables; + +if (extra_data != NULL) + { + register unsigned int flags = extra_data->flags; + if ((flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + if ((flags & PCRE_EXTRA_MATCH_LIMIT) != 0) + md->match_limit = extra_data->match_limit; + if ((flags & PCRE_EXTRA_MATCH_LIMIT_RECURSION) != 0) + md->match_limit_recursion = extra_data->match_limit_recursion; + if ((flags & PCRE_EXTRA_CALLOUT_DATA) != 0) + md->callout_data = extra_data->callout_data; + if ((flags & PCRE_EXTRA_TABLES) != 0) tables = extra_data->tables; + } + +/* If the exec call supplied NULL for tables, use the inbuilt ones. This +is a feature that makes it possible to save compiled regex and re-use them +in other programs later. */ + +if (tables == NULL) tables = PRIV(default_tables); + +/* Set up other data */ + +anchored = ((re->options | options) & PCRE_ANCHORED) != 0; +startline = (re->flags & PCRE_STARTLINE) != 0; +firstline = (re->options & PCRE_FIRSTLINE) != 0; + +/* The code starts after the real_pcre block and the capture name table. */ + +md->start_code = (const pcre_uchar *)re + re->name_table_offset + + re->name_count * re->name_entry_size; + +md->start_subject = (PCRE_PUCHAR)subject; +md->start_offset = start_offset; +md->end_subject = md->start_subject + length; +end_subject = md->end_subject; + +md->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; +md->use_ucp = (re->options & PCRE_UCP) != 0; +md->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; +md->ignore_skip_arg = FALSE; + +/* Some options are unpacked into BOOL variables in the hope that testing +them will be faster than individual option bits. */ + +md->notbol = (options & PCRE_NOTBOL) != 0; +md->noteol = (options & PCRE_NOTEOL) != 0; +md->notempty = (options & PCRE_NOTEMPTY) != 0; +md->notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; + +md->hitend = FALSE; +md->mark = md->nomatch_mark = NULL; /* In case never set */ + +md->recursive = NULL; /* No recursion at top level */ +md->hasthen = (re->flags & PCRE_HASTHEN) != 0; + +md->lcc = tables + lcc_offset; +md->fcc = tables + fcc_offset; +md->ctypes = tables + ctypes_offset; + +/* Handle different \R options. */ + +switch (options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) + { + case 0: + if ((re->options & (PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE)) != 0) + md->bsr_anycrlf = (re->options & PCRE_BSR_ANYCRLF) != 0; + else +#ifdef BSR_ANYCRLF + md->bsr_anycrlf = TRUE; +#else + md->bsr_anycrlf = FALSE; +#endif + break; + + case PCRE_BSR_ANYCRLF: + md->bsr_anycrlf = TRUE; + break; + + case PCRE_BSR_UNICODE: + md->bsr_anycrlf = FALSE; + break; + + default: return PCRE_ERROR_BADNEWLINE; + } + +/* Handle different types of newline. The three bits give eight cases. If +nothing is set at run time, whatever was used at compile time applies. */ + +switch ((((options & PCRE_NEWLINE_BITS) == 0)? re->options : + (pcre_uint32)options) & PCRE_NEWLINE_BITS) + { + case 0: newline = NEWLINE; break; /* Compile-time default */ + case PCRE_NEWLINE_CR: newline = CHAR_CR; break; + case PCRE_NEWLINE_LF: newline = CHAR_NL; break; + case PCRE_NEWLINE_CR+ + PCRE_NEWLINE_LF: newline = (CHAR_CR << 8) | CHAR_NL; break; + case PCRE_NEWLINE_ANY: newline = -1; break; + case PCRE_NEWLINE_ANYCRLF: newline = -2; break; + default: return PCRE_ERROR_BADNEWLINE; + } + +if (newline == -2) + { + md->nltype = NLTYPE_ANYCRLF; + } +else if (newline < 0) + { + md->nltype = NLTYPE_ANY; + } +else + { + md->nltype = NLTYPE_FIXED; + if (newline > 255) + { + md->nllen = 2; + md->nl[0] = (newline >> 8) & 255; + md->nl[1] = newline & 255; + } + else + { + md->nllen = 1; + md->nl[0] = newline; + } + } + +/* Partial matching was originally supported only for a restricted set of +regexes; from release 8.00 there are no restrictions, but the bits are still +defined (though never set). So there's no harm in leaving this code. */ + +if (md->partial && (re->flags & PCRE_NOPARTIAL) != 0) + return PCRE_ERROR_BADPARTIAL; + +/* If the expression has got more back references than the offsets supplied can +hold, we get a temporary chunk of working store to use during the matching. +Otherwise, we can use the vector supplied, rounding down its size to a multiple +of 3. */ + +ocount = offsetcount - (offsetcount % 3); +arg_offset_max = (2*ocount)/3; + +if (re->top_backref > 0 && re->top_backref >= ocount/3) + { + ocount = re->top_backref * 3 + 3; + md->offset_vector = (int *)(PUBL(malloc))(ocount * sizeof(int)); + if (md->offset_vector == NULL) return PCRE_ERROR_NOMEMORY; + using_temporary_offsets = TRUE; + DPRINTF(("Got memory to hold back references\n")); + } +else md->offset_vector = offsets; + +md->offset_end = ocount; +md->offset_max = (2*ocount)/3; +md->offset_overflow = FALSE; +md->capture_last = -1; + +/* Reset the working variable associated with each extraction. These should +never be used unless previously set, but they get saved and restored, and so we +initialize them to avoid reading uninitialized locations. Also, unset the +offsets for the matched string. This is really just for tidiness with callouts, +in case they inspect these fields. */ + +if (md->offset_vector != NULL) + { + register int *iptr = md->offset_vector + ocount; + 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; + } + +/* Set up the first character to match, if available. The first_char value is +never set for an anchored regular expression, but the anchoring may be forced +at run time, so we have to test for anchoring. The first char may be unset for +an unanchored pattern, of course. If there's no first char and the pattern was +studied, there may be a bitmap of possible first characters. */ + +if (!anchored) + { + if ((re->flags & PCRE_FIRSTSET) != 0) + { + has_first_char = TRUE; + first_char = first_char2 = (pcre_uchar)(re->first_char); + if ((re->flags & PCRE_FCH_CASELESS) != 0) + { + first_char2 = TABLE_GET(first_char, md->fcc, first_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (utf && first_char > 127) + first_char2 = UCD_OTHERCASE(first_char); +#endif + } + } + else + if (!startline && study != NULL && + (study->flags & PCRE_STUDY_MAPPED) != 0) + start_bits = study->start_bits; + } + +/* For anchored or unanchored matches, there may be a "last known required +character" set. */ + +if ((re->flags & PCRE_REQCHSET) != 0) + { + has_req_char = TRUE; + req_char = req_char2 = (pcre_uchar)(re->req_char); + if ((re->flags & PCRE_RCH_CASELESS) != 0) + { + req_char2 = TABLE_GET(req_char, md->fcc, req_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (utf && req_char > 127) + req_char2 = UCD_OTHERCASE(req_char); +#endif + } + } + + +/* ==========================================================================*/ + +/* Loop for handling unanchored repeated matching attempts; for anchored regexs +the loop runs just once. */ + +for(;;) + { + PCRE_PUCHAR save_end_subject = end_subject; + PCRE_PUCHAR new_start_match; + + /* If firstline is TRUE, the start of the match is constrained to the first + line of a multiline string. That is, the match must be before or at the first + newline. Implement this by temporarily adjusting end_subject so that we stop + scanning at a newline. If the match fails at the newline, later code breaks + this loop. */ + + if (firstline) + { + PCRE_PUCHAR t = start_match; +#ifdef SUPPORT_UTF + if (utf) + { + while (t < md->end_subject && !IS_NEWLINE(t)) + { + t++; + ACROSSCHAR(t < end_subject, *t, t++); + } + } + else +#endif + while (t < md->end_subject && !IS_NEWLINE(t)) t++; + end_subject = t; + } + + /* There are some optimizations that avoid running the match if a known + starting point is not found, or if a known later character is not present. + However, there is an option that disables these, for testing and for ensuring + that all callouts do actually occur. The option can be set in the regex by + (*NO_START_OPT) or passed in match-time options. */ + + if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0) + { + /* Advance to a unique first char if there is one. */ + + if (has_first_char) + { + if (first_char != first_char2) + while (start_match < end_subject && + *start_match != first_char && *start_match != first_char2) + start_match++; + else + while (start_match < end_subject && *start_match != first_char) + start_match++; + } + + /* Or to just after a linebreak for a multiline match */ + + else if (startline) + { + if (start_match > md->start_subject + start_offset) + { +#ifdef SUPPORT_UTF + if (utf) + { + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + { + start_match++; + ACROSSCHAR(start_match < end_subject, *start_match, + start_match++); + } + } + else +#endif + while (start_match < end_subject && !WAS_NEWLINE(start_match)) + start_match++; + + /* If we have just passed a CR and the newline option is ANY or ANYCRLF, + and we are now at a LF, advance the match position by one more character. + */ + + if (start_match[-1] == CHAR_CR && + (md->nltype == NLTYPE_ANY || md->nltype == NLTYPE_ANYCRLF) && + start_match < end_subject && + *start_match == CHAR_NL) + start_match++; + } + } + + /* Or to a non-unique first byte after study */ + + else if (start_bits != NULL) + { + while (start_match < end_subject) + { + register unsigned int c = *start_match; +#ifndef COMPILE_PCRE8 + if (c > 255) c = 255; +#endif + if ((start_bits[c/8] & (1 << (c&7))) == 0) + { + start_match++; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 + /* In non 8-bit mode, the iteration will stop for + characters > 255 at the beginning or not stop at all. */ + if (utf) + ACROSSCHAR(start_match < end_subject, *start_match, + start_match++); +#endif + } + else break; + } + } + } /* Starting optimizations */ + + /* Restore fudged end_subject */ + + end_subject = save_end_subject; + + /* The following two optimizations are disabled for partial matching or if + disabling is explicitly requested. */ + + if (((options | re->options) & PCRE_NO_START_OPTIMIZE) == 0 && !md->partial) + { + /* If the pattern was studied, a minimum subject length may be set. This is + a lower bound; no actual string of that length may actually match the + pattern. Although the value is, strictly, in characters, we treat it as + bytes to avoid spending too much time in this optimization. */ + + if (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0 && + (pcre_uint32)(end_subject - start_match) < study->minlength) + { + rc = MATCH_NOMATCH; + break; + } + + /* If req_char is set, we know that that character must appear in the + subject for the match to succeed. If the first character is set, req_char + must be later in the subject; otherwise the test starts at the match point. + This optimization can save a huge amount of backtracking in patterns with + nested unlimited repeats that aren't going to match. Writing separate code + for cased/caseless versions makes it go faster, as does using an + autoincrement and backing off on a match. + + HOWEVER: when the subject string is very, very long, searching to its end + can take a long time, and give bad performance on quite ordinary patterns. + This showed up when somebody was matching something like /^\d+C/ on a + 32-megabyte string... so we don't do this when the string is sufficiently + long. */ + + if (has_req_char && end_subject - start_match < REQ_BYTE_MAX) + { + register PCRE_PUCHAR p = start_match + (has_first_char? 1:0); + + /* We don't need to repeat the search if we haven't yet reached the + place we found it at last time. */ + + if (p > req_char_ptr) + { + if (req_char != req_char2) + { + while (p < end_subject) + { + register int pp = *p++; + if (pp == req_char || pp == req_char2) { p--; break; } + } + } + else + { + while (p < end_subject) + { + if (*p++ == req_char) { p--; break; } + } + } + + /* If we can't find the required character, break the matching loop, + forcing a match failure. */ + + if (p >= end_subject) + { + rc = MATCH_NOMATCH; + break; + } + + /* If we have found the required character, save the point where we + found it, so that we don't search again next time round the loop if + the start hasn't passed this character yet. */ + + req_char_ptr = p; + } + } + } + +#ifdef PCRE_DEBUG /* Sigh. Some compilers never learn. */ + printf(">>>> Match against: "); + pchars(start_match, end_subject - start_match, TRUE, md); + printf("\n"); +#endif + + /* OK, we can now run the match. If "hitend" is set afterwards, remember the + first starting point for which a partial match was found. */ + + md->start_match_ptr = start_match; + md->start_used_ptr = start_match; + md->match_call_count = 0; + md->match_function_type = 0; + md->end_offset_top = 0; + rc = match(start_match, md->start_code, start_match, 2, md, NULL, 0); + if (md->hitend && start_partial == NULL) start_partial = md->start_used_ptr; + + switch(rc) + { + /* If MATCH_SKIP_ARG reaches this level it means that a MARK that matched + the SKIP's arg was not found. In this circumstance, Perl ignores the SKIP + entirely. The only way we can do that is to re-do the match at the same + point, with a flag to force SKIP with an argument to be ignored. Just + treating this case as NOMATCH does not work because it does not check other + alternatives in patterns such as A(*SKIP:A)B|AC when the subject is AC. */ + + case MATCH_SKIP_ARG: + new_start_match = start_match; + md->ignore_skip_arg = TRUE; + break; + + /* SKIP passes back the next starting point explicitly, but if it is the + same as the match we have just done, treat it as NOMATCH. */ + + case MATCH_SKIP: + if (md->start_match_ptr != start_match) + { + new_start_match = md->start_match_ptr; + break; + } + /* Fall through */ + + /* NOMATCH and PRUNE advance by one character. THEN at this level acts + exactly like PRUNE. Unset the ignore SKIP-with-argument flag. */ + + case MATCH_NOMATCH: + case MATCH_PRUNE: + case MATCH_THEN: + md->ignore_skip_arg = FALSE; + new_start_match = start_match + 1; +#ifdef SUPPORT_UTF + if (utf) + ACROSSCHAR(new_start_match < end_subject, *new_start_match, + new_start_match++); +#endif + break; + + /* COMMIT disables the bumpalong, but otherwise behaves as NOMATCH. */ + + case MATCH_COMMIT: + rc = MATCH_NOMATCH; + goto ENDLOOP; + + /* Any other return is either a match, or some kind of error. */ + + default: + goto ENDLOOP; + } + + /* Control reaches here for the various types of "no match at this point" + result. Reset the code to MATCH_NOMATCH for subsequent checking. */ + + rc = MATCH_NOMATCH; + + /* If PCRE_FIRSTLINE is set, the match must happen before or at the first + newline in the subject (though it may continue over the newline). Therefore, + if we have just failed to match, starting at a newline, do not continue. */ + + if (firstline && IS_NEWLINE(start_match)) break; + + /* Advance to new matching position */ + + start_match = new_start_match; + + /* Break the loop if the pattern is anchored or if we have passed the end of + the subject. */ + + if (anchored || start_match > end_subject) break; + + /* If we have just passed a CR and we are now at a LF, and the pattern does + not contain any explicit matches for \r or \n, and the newline option is CRLF + or ANY or ANYCRLF, advance the match position by one more character. In + normal matching start_match will aways be greater than the first position at + this stage, but a failed *SKIP can cause a return at the same point, which is + why the first test exists. */ + + if (start_match > (PCRE_PUCHAR)subject + start_offset && + start_match[-1] == CHAR_CR && + start_match < end_subject && + *start_match == CHAR_NL && + (re->flags & PCRE_HASCRORLF) == 0 && + (md->nltype == NLTYPE_ANY || + md->nltype == NLTYPE_ANYCRLF || + md->nllen == 2)) + start_match++; + + md->mark = NULL; /* Reset for start of next match attempt */ + } /* End of for(;;) "bumpalong" loop */ + +/* ==========================================================================*/ + +/* We reach here when rc is not MATCH_NOMATCH, or if one of the stopping +conditions is true: + +(1) The pattern is anchored or the match was failed by (*COMMIT); + +(2) We are past the end of the subject; + +(3) PCRE_FIRSTLINE is set and we have failed to match at a newline, because + this option requests that a match occur at or before the first newline in + the subject. + +When we have a match and the offset vector is big enough to deal with any +backreferences, captured substring offsets will already be set up. In the case +where we had to get some local store to hold offsets for backreference +processing, copy those that we can. In this case there need not be overflow if +certain parts of the pattern were not used, even though there are more +capturing parentheses than vector slots. */ + +ENDLOOP: + +if (rc == MATCH_MATCH || rc == MATCH_ACCEPT) + { + if (using_temporary_offsets) + { + if (arg_offset_max >= 4) + { + memcpy(offsets + 2, md->offset_vector + 2, + (arg_offset_max - 2) * sizeof(int)); + DPRINTF(("Copied offsets from temporary memory\n")); + } + if (md->end_offset_top > arg_offset_max) md->offset_overflow = TRUE; + DPRINTF(("Freeing temporary memory\n")); + (PUBL(free))(md->offset_vector); + } + + /* Set the return code to the number of captured strings, or 0 if there were + too many to fit into the vector. */ + + rc = (md->offset_overflow && md->end_offset_top >= arg_offset_max)? + 0 : md->end_offset_top/2; + + /* If there is space in the offset vector, set any unused pairs at the end of + the pattern to -1 for backwards compatibility. It is documented that this + happens. In earlier versions, the whole set of potential capturing offsets + was set to -1 each time round the loop, but this is handled differently now. + "Gaps" are set to -1 dynamically instead (this fixes a bug). Thus, it is only + those at the end that need unsetting here. We can't just unset them all at + the start of the whole thing because they may get set in one branch that is + not the final matching branch. */ + + if (md->end_offset_top/2 <= re->top_bracket && offsets != NULL) + { + register int *iptr, *iend; + int resetcount = 2 + re->top_bracket * 2; + if (resetcount > offsetcount) resetcount = ocount; + iptr = offsets + md->end_offset_top; + iend = offsets + resetcount; + while (iptr < iend) *iptr++ = -1; + } + + /* If there is space, set up the whole thing as substring 0. The value of + md->start_match_ptr might be modified if \K was encountered on the success + matching path. */ + + if (offsetcount < 2) rc = 0; else + { + offsets[0] = (int)(md->start_match_ptr - md->start_subject); + offsets[1] = (int)(md->end_match_ptr - md->start_subject); + } + + /* Return MARK data if requested */ + + if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) + *(extra_data->mark) = (pcre_uchar *)md->mark; + DPRINTF((">>>> returning %d\n", rc)); + return rc; + } + +/* Control gets here if there has been an error, or if the overall match +attempt has failed at all permitted starting positions. */ + +if (using_temporary_offsets) + { + DPRINTF(("Freeing temporary memory\n")); + (PUBL(free))(md->offset_vector); + } + +/* For anything other than nomatch or partial match, just return the code. */ + +if (rc != MATCH_NOMATCH && rc != PCRE_ERROR_PARTIAL) + { + DPRINTF((">>>> error: returning %d\n", rc)); + return rc; + } + +/* Handle partial matches - disable any mark data */ + +if (start_partial != NULL) + { + DPRINTF((">>>> returning PCRE_ERROR_PARTIAL\n")); + md->mark = NULL; + if (offsetcount > 1) + { + offsets[0] = (int)(start_partial - (PCRE_PUCHAR)subject); + offsets[1] = (int)(end_subject - (PCRE_PUCHAR)subject); + } + rc = PCRE_ERROR_PARTIAL; + } + +/* This is the classic nomatch case */ + +else + { + DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n")); + rc = PCRE_ERROR_NOMATCH; + } + +/* Return the MARK data if it has been requested. */ + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_MARK) != 0) + *(extra_data->mark) = (pcre_uchar *)md->nomatch_mark; +return rc; +} + +/* End of pcre_exec.c */ diff --git a/src/3rdparty/pcre/pcre_fullinfo.c b/src/3rdparty/pcre/pcre_fullinfo.c new file mode 100644 index 0000000000..e5e68f3f29 --- /dev/null +++ b/src/3rdparty/pcre/pcre_fullinfo.c @@ -0,0 +1,202 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_fullinfo(), which returns +information about a compiled pattern. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Return info about compiled pattern * +*************************************************/ + +/* This is a newer "info" function which has an extensible interface so +that additional items can be added compatibly. + +Arguments: + argument_re points to compiled code + extra_data points extra data, or NULL + what what information is required + where where to put the information + +Returns: 0 if data returned, negative on error +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data, + int what, void *where) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data, + int what, void *where) +#endif +{ +const REAL_PCRE *re = (const REAL_PCRE *)argument_re; +const pcre_study_data *study = NULL; + +if (re == NULL || where == NULL) return PCRE_ERROR_NULL; + +if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0) + study = (const pcre_study_data *)extra_data->study_data; + +/* Check that the first field in the block is the magic number. If it is not, +return with PCRE_ERROR_BADMAGIC. However, if the magic number is equal to +REVERSED_MAGIC_NUMBER we return with PCRE_ERROR_BADENDIANNESS, which +means that the pattern is likely compiled with different endianness. */ + +if (re->magic_number != MAGIC_NUMBER) + return re->magic_number == REVERSED_MAGIC_NUMBER? + PCRE_ERROR_BADENDIANNESS:PCRE_ERROR_BADMAGIC; + +/* Check that this pattern was compiled in the correct bit mode */ + +if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; + +switch (what) + { + case PCRE_INFO_OPTIONS: + *((unsigned long int *)where) = re->options & PUBLIC_COMPILE_OPTIONS; + break; + + case PCRE_INFO_SIZE: + *((size_t *)where) = re->size; + break; + + case PCRE_INFO_STUDYSIZE: + *((size_t *)where) = (study == NULL)? 0 : study->size; + break; + + case PCRE_INFO_JITSIZE: +#ifdef SUPPORT_JIT + *((size_t *)where) = + (extra_data != NULL && + (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && + extra_data->executable_jit != NULL)? + PRIV(jit_get_size)(extra_data->executable_jit) : 0; +#else + *((size_t *)where) = 0; +#endif + break; + + case PCRE_INFO_CAPTURECOUNT: + *((int *)where) = re->top_bracket; + break; + + case PCRE_INFO_BACKREFMAX: + *((int *)where) = re->top_backref; + break; + + case PCRE_INFO_FIRSTBYTE: + *((int *)where) = + ((re->flags & PCRE_FIRSTSET) != 0)? re->first_char : + ((re->flags & PCRE_STARTLINE) != 0)? -1 : -2; + break; + + /* Make sure we pass back the pointer to the bit vector in the external + block, not the internal copy (with flipped integer fields). */ + + case PCRE_INFO_FIRSTTABLE: + *((const pcre_uint8 **)where) = + (study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)? + ((const pcre_study_data *)extra_data->study_data)->start_bits : NULL; + break; + + case PCRE_INFO_MINLENGTH: + *((int *)where) = + (study != NULL && (study->flags & PCRE_STUDY_MINLEN) != 0)? + (int)(study->minlength) : -1; + break; + + case PCRE_INFO_JIT: + *((int *)where) = extra_data != NULL && + (extra_data->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && + extra_data->executable_jit != NULL; + break; + + case PCRE_INFO_LASTLITERAL: + *((int *)where) = + ((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1; + break; + + case PCRE_INFO_NAMEENTRYSIZE: + *((int *)where) = re->name_entry_size; + break; + + case PCRE_INFO_NAMECOUNT: + *((int *)where) = re->name_count; + break; + + case PCRE_INFO_NAMETABLE: + *((const pcre_uchar **)where) = (const pcre_uchar *)re + re->name_table_offset; + break; + + case PCRE_INFO_DEFAULT_TABLES: + *((const pcre_uint8 **)where) = (const pcre_uint8 *)(PRIV(default_tables)); + break; + + /* From release 8.00 this will always return TRUE because NOPARTIAL is + no longer ever set (the restrictions have been removed). */ + + case PCRE_INFO_OKPARTIAL: + *((int *)where) = (re->flags & PCRE_NOPARTIAL) == 0; + break; + + case PCRE_INFO_JCHANGED: + *((int *)where) = (re->flags & PCRE_JCHANGED) != 0; + break; + + case PCRE_INFO_HASCRORLF: + *((int *)where) = (re->flags & PCRE_HASCRORLF) != 0; + break; + + default: return PCRE_ERROR_BADOPTION; + } + +return 0; +} + +/* End of pcre_fullinfo.c */ diff --git a/src/3rdparty/pcre/pcre_get.c b/src/3rdparty/pcre/pcre_get.c new file mode 100644 index 0000000000..daecb695fe --- /dev/null +++ b/src/3rdparty/pcre/pcre_get.c @@ -0,0 +1,587 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains some convenience functions for extracting substrings +from the subject string after a regex match has succeeded. The original idea +for these functions came from Scott Wimer. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Find number for named string * +*************************************************/ + +/* This function is used by the get_first_set() function below, as well +as being generally available. It assumes that names are unique. + +Arguments: + code the compiled regex + stringname the name whose number is required + +Returns: the number of the named parentheses, or a negative number + (PCRE_ERROR_NOSUBSTRING) if not found +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_stringnumber(const pcre *code, const char *stringname) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname) +#endif +{ +int rc; +int entrysize; +int top, bot; +pcre_uchar *nametable; + +#ifdef COMPILE_PCRE8 +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; +#endif +#ifdef COMPILE_PCRE16 +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; +#endif + +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + pcre_uchar *entry = nametable + entrysize*mid; + int c = STRCMP_UC_UC((pcre_uchar *)stringname, + (pcre_uchar *)(entry + IMM2_SIZE)); + if (c == 0) return GET2(entry, 0); + if (c > 0) bot = mid + 1; else top = mid; + } + +return PCRE_ERROR_NOSUBSTRING; +} + + + +/************************************************* +* Find (multiple) entries for named string * +*************************************************/ + +/* This is used by the get_first_set() function below, as well as being +generally available. It is used when duplicated names are permitted. + +Arguments: + code the compiled regex + stringname the name whose entries required + firstptr where to put the pointer to the first entry + lastptr where to put the pointer to the last entry + +Returns: the length of each entry, or a negative number + (PCRE_ERROR_NOSUBSTRING) if not found +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_stringtable_entries(const pcre *code, const char *stringname, + char **firstptr, char **lastptr) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname, + PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr) +#endif +{ +int rc; +int entrysize; +int top, bot; +pcre_uchar *nametable, *lastentry; + +#ifdef COMPILE_PCRE8 +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; +#endif +#ifdef COMPILE_PCRE16 +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0) + return rc; +if (top <= 0) return PCRE_ERROR_NOSUBSTRING; + +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0) + return rc; +if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0) + return rc; +#endif + +lastentry = nametable + entrysize * (top - 1); +bot = 0; +while (top > bot) + { + int mid = (top + bot) / 2; + pcre_uchar *entry = nametable + entrysize*mid; + int c = STRCMP_UC_UC((pcre_uchar *)stringname, + (pcre_uchar *)(entry + IMM2_SIZE)); + if (c == 0) + { + pcre_uchar *first = entry; + pcre_uchar *last = entry; + while (first > nametable) + { + if (STRCMP_UC_UC((pcre_uchar *)stringname, + (pcre_uchar *)(first - entrysize + IMM2_SIZE)) != 0) break; + first -= entrysize; + } + while (last < lastentry) + { + if (STRCMP_UC_UC((pcre_uchar *)stringname, + (pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break; + last += entrysize; + } +#ifdef COMPILE_PCRE8 + *firstptr = (char *)first; + *lastptr = (char *)last; +#else + *firstptr = (PCRE_UCHAR16 *)first; + *lastptr = (PCRE_UCHAR16 *)last; +#endif + return entrysize; + } + if (c > 0) bot = mid + 1; else top = mid; + } + +return PCRE_ERROR_NOSUBSTRING; +} + + + +/************************************************* +* Find first set of multiple named strings * +*************************************************/ + +/* This function allows for duplicate names in the table of named substrings. +It returns the number of the first one that was set in a pattern match. + +Arguments: + code the compiled regex + stringname the name of the capturing substring + ovector the vector of matched substrings + +Returns: the number of the first that is set, + or the number of the last one if none are set, + or a negative number on error +*/ + +#ifdef COMPILE_PCRE8 +static int +get_first_set(const pcre *code, const char *stringname, int *ovector) +#else +static int +get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector) +#endif +{ +const REAL_PCRE *re = (const REAL_PCRE *)code; +int entrysize; +pcre_uchar *entry; +#ifdef COMPILE_PCRE8 +char *first, *last; +#else +PCRE_UCHAR16 *first, *last; +#endif + +#ifdef COMPILE_PCRE8 +if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) + return pcre_get_stringnumber(code, stringname); +entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last); +#else +if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0) + return pcre16_get_stringnumber(code, stringname); +entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last); +#endif +if (entrysize <= 0) return entrysize; +for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize) + { + int n = GET2(entry, 0); + if (ovector[n*2] >= 0) return n; + } +return GET2(entry, 0); +} + + + + +/************************************************* +* Copy captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer. +Note that we use memcpy() rather than strncpy() in case there are binary zeros +in the string. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_copy_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, char *buffer, int size) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, + int stringnumber, PCRE_UCHAR16 *buffer, int size) +#endif +{ +int yield; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +if (size < yield + 1) return PCRE_ERROR_NOMEMORY; +memcpy(buffer, subject + ovector[stringnumber], IN_UCHARS(yield)); +buffer[yield] = 0; +return yield; +} + + + +/************************************************* +* Copy named captured string to given buffer * +*************************************************/ + +/* This function copies a single captured substring into a given buffer, +identifying it by name. If the regex permits duplicate names, the first +substring that is set is chosen. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + buffer where to put the substring + size the size of the buffer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) buffer too small + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_copy_named_substring(const pcre *code, const char *subject, + int *ovector, int stringcount, const char *stringname, + char *buffer, int size) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject, + int *ovector, int stringcount, PCRE_SPTR16 stringname, + PCRE_UCHAR16 *buffer, int size) +#endif +{ +int n = get_first_set(code, stringname, ovector); +if (n <= 0) return n; +#ifdef COMPILE_PCRE8 +return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size); +#else +return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size); +#endif +} + + + +/************************************************* +* Copy all captured strings to new store * +*************************************************/ + +/* This function gets one chunk of store and builds a list of pointers and all +of the captured substrings in it. A NULL pointer is put on the end of the list. + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + listptr set to point to the list of pointers + +Returns: if successful: 0 + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_substring_list(const char *subject, int *ovector, int stringcount, + const char ***listptr) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount, + PCRE_SPTR16 **listptr) +#endif +{ +int i; +int size = sizeof(pcre_uchar *); +int double_count = stringcount * 2; +pcre_uchar **stringlist; +pcre_uchar *p; + +for (i = 0; i < double_count; i += 2) + size += sizeof(pcre_uchar *) + IN_UCHARS(ovector[i+1] - ovector[i] + 1); + +stringlist = (pcre_uchar **)(PUBL(malloc))(size); +if (stringlist == NULL) return PCRE_ERROR_NOMEMORY; + +#ifdef COMPILE_PCRE8 +*listptr = (const char **)stringlist; +#else +*listptr = (PCRE_SPTR16 *)stringlist; +#endif +p = (pcre_uchar *)(stringlist + stringcount + 1); + +for (i = 0; i < double_count; i += 2) + { + int len = ovector[i+1] - ovector[i]; + memcpy(p, subject + ovector[i], IN_UCHARS(len)); + *stringlist++ = p; + p += len; + *p++ = 0; + } + +*stringlist = NULL; +return 0; +} + + + +/************************************************* +* Free store obtained by get_substring_list * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (PUBL(free))() +directly. + +Argument: the result of a previous pcre_get_substring_list() +Returns: nothing +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre_free_substring_list(const char **pointer) +#else +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre16_free_substring_list(PCRE_SPTR16 *pointer) +#endif +{ +(PUBL(free))((void *)pointer); +} + + + +/************************************************* +* Copy captured string to new store * +*************************************************/ + +/* This function copies a single captured substring into a piece of new +store + +Arguments: + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringnumber the number of the required substring + stringptr where to put a pointer to the substring + +Returns: if successful: + the length of the string, not including the zero that + is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) failed to get store + PCRE_ERROR_NOSUBSTRING (-7) substring not present +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_substring(const char *subject, int *ovector, int stringcount, + int stringnumber, const char **stringptr) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount, + int stringnumber, PCRE_SPTR16 *stringptr) +#endif +{ +int yield; +pcre_uchar *substring; +if (stringnumber < 0 || stringnumber >= stringcount) + return PCRE_ERROR_NOSUBSTRING; +stringnumber *= 2; +yield = ovector[stringnumber+1] - ovector[stringnumber]; +substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1)); +if (substring == NULL) return PCRE_ERROR_NOMEMORY; +memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield)); +substring[yield] = 0; +#ifdef COMPILE_PCRE8 +*stringptr = (const char *)substring; +#else +*stringptr = (PCRE_SPTR16)substring; +#endif +return yield; +} + + + +/************************************************* +* Copy named captured string to new store * +*************************************************/ + +/* This function copies a single captured substring, identified by name, into +new store. If the regex permits duplicate names, the first substring that is +set is chosen. + +Arguments: + code the compiled regex + subject the subject string that was matched + ovector pointer to the offsets table + stringcount the number of substrings that were captured + (i.e. the yield of the pcre_exec call, unless + that was zero, in which case it should be 1/3 + of the offset table size) + stringname the name of the required substring + stringptr where to put the pointer + +Returns: if successful: + the length of the copied string, not including the zero + that is put on the end; can be zero + if not successful: + PCRE_ERROR_NOMEMORY (-6) couldn't get memory + PCRE_ERROR_NOSUBSTRING (-7) no such captured substring +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_get_named_substring(const pcre *code, const char *subject, + int *ovector, int stringcount, const char *stringname, + const char **stringptr) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject, + int *ovector, int stringcount, PCRE_SPTR16 stringname, + PCRE_SPTR16 *stringptr) +#endif +{ +int n = get_first_set(code, stringname, ovector); +if (n <= 0) return n; +#ifdef COMPILE_PCRE8 +return pcre_get_substring(subject, ovector, stringcount, n, stringptr); +#else +return pcre16_get_substring(subject, ovector, stringcount, n, stringptr); +#endif +} + + + + +/************************************************* +* Free store obtained by get_substring * +*************************************************/ + +/* This function exists for the benefit of people calling PCRE from non-C +programs that can call its functions, but not free() or (PUBL(free))() +directly. + +Argument: the result of a previous pcre_get_substring() +Returns: nothing +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre_free_substring(const char *pointer) +#else +PCRE_EXP_DEFN void PCRE_CALL_CONVENTION +pcre16_free_substring(PCRE_SPTR16 pointer) +#endif +{ +(PUBL(free))((void *)pointer); +} + +/* End of pcre_get.c */ diff --git a/src/3rdparty/pcre/pcre_globals.c b/src/3rdparty/pcre/pcre_globals.c new file mode 100644 index 0000000000..d5b6286fc2 --- /dev/null +++ b/src/3rdparty/pcre/pcre_globals.c @@ -0,0 +1,84 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains global variables that are exported by the PCRE library. +PCRE is thread-clean and doesn't use any global variables in the normal sense. +However, it calls memory allocation and freeing functions via the four +indirections below, and it can optionally do callouts, using the fifth +indirection. These values can be changed by the caller, but are shared between +all threads. + +For MS Visual Studio and Symbian OS, there are problems in initializing these +variables to non-local functions. In these cases, therefore, an indirection via +a local function is used. + +Also, when compiling for Virtual Pascal, things are done differently, and +global variables are not used. */ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#if defined _MSC_VER || defined __SYMBIAN32__ +static void* LocalPcreMalloc(size_t aSize) + { + return malloc(aSize); + } +static void LocalPcreFree(void* aPtr) + { + free(aPtr); + } +PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = LocalPcreMalloc; +PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = LocalPcreFree; +PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = LocalPcreMalloc; +PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = LocalPcreFree; +PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; + +#elif !defined VPCOMPAT +PCRE_EXP_DATA_DEFN void *(*PUBL(malloc))(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*PUBL(free))(void *) = free; +PCRE_EXP_DATA_DEFN void *(*PUBL(stack_malloc))(size_t) = malloc; +PCRE_EXP_DATA_DEFN void (*PUBL(stack_free))(void *) = free; +PCRE_EXP_DATA_DEFN int (*PUBL(callout))(PUBL(callout_block) *) = NULL; +#endif + +/* End of pcre_globals.c */ diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h new file mode 100644 index 0000000000..e5a4b6a526 --- /dev/null +++ b/src/3rdparty/pcre/pcre_internal.h @@ -0,0 +1,2332 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +/* This header contains definitions that are shared between the different +modules, but which are not relevant to the exported API. This includes some +functions whose names all begin with "_pcre_" or "_pcre16_" depending on +the PRIV macro. */ + +#ifndef PCRE_INTERNAL_H +#define PCRE_INTERNAL_H + +/* Define PCRE_DEBUG to get debugging output on stdout. */ + +#if 0 +#define PCRE_DEBUG +#endif + +/* PCRE is compiled as an 8 bit library if it is not requested otherwise. */ +#ifndef COMPILE_PCRE16 +#define COMPILE_PCRE8 +#endif + +/* If SUPPORT_UCP is defined, SUPPORT_UTF must also be defined. The +"configure" script ensures this, but not everybody uses "configure". */ + +#if defined SUPPORT_UCP && !(defined SUPPORT_UTF) +#define SUPPORT_UTF 1 +#endif + +/* We define SUPPORT_UTF if SUPPORT_UTF8 is enabled for compatibility +reasons with existing code. */ + +#if defined SUPPORT_UTF8 && !(defined SUPPORT_UTF) +#define SUPPORT_UTF 1 +#endif + +/* Fixme: SUPPORT_UTF8 should be eventually disappear from the code. +Until then we define it if SUPPORT_UTF is defined. */ + +#if defined SUPPORT_UTF && !(defined SUPPORT_UTF8) +#define SUPPORT_UTF8 1 +#endif + +/* We do not support both EBCDIC and UTF-8/16 at the same time. The "configure" +script prevents both being selected, but not everybody uses "configure". */ + +#if defined EBCDIC && defined SUPPORT_UTF +#error The use of both EBCDIC and SUPPORT_UTF8/16 is not supported. +#endif + +/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef +inline, and there are *still* stupid compilers about that don't like indented +pre-processor statements, or at least there were when I first wrote this. After +all, it had only been about 10 years then... + +It turns out that the Mac Debugging.h header also defines the macro DPRINTF, so +be absolutely sure we get our version. */ + +#undef DPRINTF +#ifdef PCRE_DEBUG +#define DPRINTF(p) printf p +#else +#define DPRINTF(p) /* Nothing */ +#endif + + +/* Standard C headers plus the external interface definition. The only time +setjmp and stdarg are used is when NO_RECURSE is set. */ + +#include +#include +#include +#include +#include +#include + +/* When compiling a DLL for Windows, the exported symbols have to be declared +using some MS magic. I found some useful information on this web page: +http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the +information there, using __declspec(dllexport) without "extern" we have a +definition; with "extern" we have a declaration. The settings here override the +setting in pcre.h (which is included below); it defines only PCRE_EXP_DECL, +which is all that is needed for applications (they just import the symbols). We +use: + + PCRE_EXP_DECL for declarations + PCRE_EXP_DEFN for definitions of exported functions + PCRE_EXP_DATA_DEFN for definitions of exported variables + +The reason for the two DEFN macros is that in non-Windows environments, one +does not want to have "extern" before variable definitions because it leads to +compiler warnings. So we distinguish between functions and variables. In +Windows, the two should always be the same. + +The reason for wrapping this in #ifndef PCRE_EXP_DECL is so that pcretest, +which is an application, but needs to import this file in order to "peek" at +internals, can #include pcre.h first to get an application's-eye view. + +In principle, people compiling for non-Windows, non-Unix-like (i.e. uncommon, +special-purpose environments) might want to stick other stuff in front of +exported symbols. That's why, in the non-Windows case, we set PCRE_EXP_DEFN and +PCRE_EXP_DATA_DEFN only if they are not already set. */ + +#ifndef PCRE_EXP_DECL +# ifdef _WIN32 +# ifndef PCRE_STATIC +# define PCRE_EXP_DECL extern __declspec(dllexport) +# define PCRE_EXP_DEFN __declspec(dllexport) +# define PCRE_EXP_DATA_DEFN __declspec(dllexport) +# else +# define PCRE_EXP_DECL extern +# define PCRE_EXP_DEFN +# define PCRE_EXP_DATA_DEFN +# endif +# else +# ifdef __cplusplus +# define PCRE_EXP_DECL extern "C" +# else +# define PCRE_EXP_DECL extern +# endif +# ifndef PCRE_EXP_DEFN +# define PCRE_EXP_DEFN PCRE_EXP_DECL +# endif +# ifndef PCRE_EXP_DATA_DEFN +# define PCRE_EXP_DATA_DEFN +# endif +# endif +#endif + +/* When compiling with the MSVC compiler, it is sometimes necessary to include +a "calling convention" before exported function names. (This is secondhand +information; I know nothing about MSVC myself). For example, something like + + void __cdecl function(....) + +might be needed. In order so make this easy, all the exported functions have +PCRE_CALL_CONVENTION just before their names. It is rarely needed; if not +set, we ensure here that it has no effect. */ + +#ifndef PCRE_CALL_CONVENTION +#define PCRE_CALL_CONVENTION +#endif + +/* We need to have types that specify unsigned 8, 16 and 32-bit integers. We +cannot determine these outside the compilation (e.g. by running a program as +part of "configure") because PCRE is often cross-compiled for use on other +systems. Instead we make use of the maximum sizes that are available at +preprocessor time in standard C environments. */ + +typedef unsigned char pcre_uint8; + +#if USHRT_MAX == 65535 + typedef unsigned short pcre_uint16; + typedef short pcre_int16; +#elif UINT_MAX == 65535 + typedef unsigned int pcre_uint16; + typedef int pcre_int16; +#else + #error Cannot determine a type for 16-bit unsigned integers +#endif + +#if UINT_MAX == 4294967295 + typedef unsigned int pcre_uint32; + typedef int pcre_int32; +#elif ULONG_MAX == 4294967295 + typedef unsigned long int pcre_uint32; + typedef long int pcre_int32; +#else + #error Cannot determine a type for 32-bit unsigned integers +#endif + +/* When checking for integer overflow in pcre_compile(), we need to handle +large integers. If a 64-bit integer type is available, we can use that. +Otherwise we have to cast to double, which of course requires floating point +arithmetic. Handle this by defining a macro for the appropriate type. If +stdint.h is available, include it; it may define INT64_MAX. Systems that do not +have stdint.h (e.g. Solaris) may have inttypes.h. The macro int64_t may be set +by "configure". */ + +#if HAVE_STDINT_H +#include +#elif HAVE_INTTYPES_H +#include +#endif + +#if defined INT64_MAX || defined int64_t +#define INT64_OR_DOUBLE int64_t +#else +#define INT64_OR_DOUBLE double +#endif + +/* All character handling must be done as unsigned characters. Otherwise there +are problems with top-bit-set characters and functions such as isspace(). +However, we leave the interface to the outside world as char * or short *, +because that should make things easier for callers. This character type is +called pcre_uchar. + +The IN_UCHARS macro multiply its argument with the byte size of the current +pcre_uchar type. Useful for memcpy and such operations, whose require the +byte size of their input/output buffers. + +The MAX_255 macro checks whether its pcre_uchar input is less than 256. + +The TABLE_GET macro is designed for accessing elements of tables whose contain +exactly 256 items. When the character is able to contain more than 256 +items, some check is needed before accessing these tables. +*/ + +#ifdef COMPILE_PCRE8 + +typedef unsigned char pcre_uchar; +#define IN_UCHARS(x) (x) +#define MAX_255(c) 1 +#define TABLE_GET(c, table, default) ((table)[c]) + +#else + +#ifdef COMPILE_PCRE16 +#if USHRT_MAX != 65535 +/* This is a warning message. Change PCRE_UCHAR16 to a 16 bit data type in +pcre.h(.in) and disable (comment out) this message. */ +#error Warning: PCRE_UCHAR16 is not a 16 bit data type. +#endif + +typedef pcre_uint16 pcre_uchar; +#define IN_UCHARS(x) ((x) << 1) +#define MAX_255(c) ((c) <= 255u) +#define TABLE_GET(c, table, default) (MAX_255(c)? ((table)[c]):(default)) + +#else +#error Unsupported compiling mode +#endif /* COMPILE_PCRE16 */ + +#endif /* COMPILE_PCRE8 */ + +/* This is an unsigned int value that no character can ever have. UTF-8 +characters only go up to 0x7fffffff (though Unicode doesn't go beyond +0x0010ffff). */ + +#define NOTACHAR 0xffffffff + +/* PCRE is able to support several different kinds of newline (CR, LF, CRLF, +"any" and "anycrlf" at present). The following macros are used to package up +testing for newlines. NLBLOCK, PSSTART, and PSEND are defined in the various +modules to indicate in which datablock the parameters exist, and what the +start/end of string field names are. */ + +#define NLTYPE_FIXED 0 /* Newline is a fixed length string */ +#define NLTYPE_ANY 1 /* Newline is any Unicode line ending */ +#define NLTYPE_ANYCRLF 2 /* Newline is CR, LF, or CRLF */ + +/* This macro checks for a newline at the given position */ + +#define IS_NEWLINE(p) \ + ((NLBLOCK->nltype != NLTYPE_FIXED)? \ + ((p) < NLBLOCK->PSEND && \ + PRIV(is_newline)((p), NLBLOCK->nltype, NLBLOCK->PSEND, \ + &(NLBLOCK->nllen), utf)) \ + : \ + ((p) <= NLBLOCK->PSEND - NLBLOCK->nllen && \ + (p)[0] == NLBLOCK->nl[0] && \ + (NLBLOCK->nllen == 1 || (p)[1] == NLBLOCK->nl[1]) \ + ) \ + ) + +/* This macro checks for a newline immediately preceding the given position */ + +#define WAS_NEWLINE(p) \ + ((NLBLOCK->nltype != NLTYPE_FIXED)? \ + ((p) > NLBLOCK->PSSTART && \ + PRIV(was_newline)((p), NLBLOCK->nltype, NLBLOCK->PSSTART, \ + &(NLBLOCK->nllen), utf)) \ + : \ + ((p) >= NLBLOCK->PSSTART + NLBLOCK->nllen && \ + (p)[-NLBLOCK->nllen] == NLBLOCK->nl[0] && \ + (NLBLOCK->nllen == 1 || (p)[-NLBLOCK->nllen+1] == NLBLOCK->nl[1]) \ + ) \ + ) + +/* When PCRE is compiled as a C++ library, the subject pointer can be replaced +with a custom type. This makes it possible, for example, to allow pcre_exec() +to process subject strings that are discontinuous by using a smart pointer +class. It must always be possible to inspect all of the subject string in +pcre_exec() because of the way it backtracks. Two macros are required in the +normal case, for sign-unspecified and unsigned char pointers. The former is +used for the external interface and appears in pcre.h, which is why its name +must begin with PCRE_. */ + +#ifdef CUSTOM_SUBJECT_PTR +#define PCRE_PUCHAR CUSTOM_SUBJECT_PTR +#else +#define PCRE_PUCHAR const pcre_uchar * +#endif + +/* Include the public PCRE header and the definitions of UCP character property +values. */ + +#include "pcre.h" +#include "ucp.h" + +/* When compiling for use with the Virtual Pascal compiler, these functions +need to have their names changed. PCRE must be compiled with the -DVPCOMPAT +option on the command line. */ + +#ifdef VPCOMPAT +#define strlen(s) _strlen(s) +#define strncmp(s1,s2,m) _strncmp(s1,s2,m) +#define memcmp(s,c,n) _memcmp(s,c,n) +#define memcpy(d,s,n) _memcpy(d,s,n) +#define memmove(d,s,n) _memmove(d,s,n) +#define memset(s,c,n) _memset(s,c,n) +#else /* VPCOMPAT */ + +/* To cope with SunOS4 and other systems that lack memmove() but have bcopy(), +define a macro for memmove() if HAVE_MEMMOVE is false, provided that HAVE_BCOPY +is set. Otherwise, include an emulating function for those systems that have +neither (there some non-Unix environments where this is the case). */ + +#ifndef HAVE_MEMMOVE +#undef memmove /* some systems may have a macro */ +#ifdef HAVE_BCOPY +#define memmove(a, b, c) bcopy(b, a, c) +#else /* HAVE_BCOPY */ +static void * +pcre_memmove(void *d, const void *s, size_t n) +{ +size_t i; +unsigned char *dest = (unsigned char *)d; +const unsigned char *src = (const unsigned char *)s; +if (dest > src) + { + dest += n; + src += n; + for (i = 0; i < n; ++i) *(--dest) = *(--src); + return (void *)dest; + } +else + { + for (i = 0; i < n; ++i) *dest++ = *src++; + return (void *)(dest - n); + } +} +#define memmove(a, b, c) pcre_memmove(a, b, c) +#endif /* not HAVE_BCOPY */ +#endif /* not HAVE_MEMMOVE */ +#endif /* not VPCOMPAT */ + + +/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored +in big-endian order) by default. These are used, for example, to link from the +start of a subpattern to its alternatives and its end. The use of 2 bytes per +offset limits the size of the compiled regex to around 64K, which is big enough +for almost everybody. However, I received a request for an even bigger limit. +For this reason, and also to make the code easier to maintain, the storing and +loading of offsets from the byte string is now handled by the macros that are +defined here. + +The macros are controlled by the value of LINK_SIZE. This defaults to 2 in +the config.h file, but can be overridden by using -D on the command line. This +is automated on Unix systems via the "configure" command. */ + +#ifdef COMPILE_PCRE8 + +#if LINK_SIZE == 2 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 8), \ + (a[(n)+1] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#define MAX_PATTERN_SIZE (1 << 16) + + +#elif LINK_SIZE == 3 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 16), \ + (a[(n)+1] = (d) >> 8), \ + (a[(n)+2] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2]) + +#define MAX_PATTERN_SIZE (1 << 24) + + +#elif LINK_SIZE == 4 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 24), \ + (a[(n)+1] = (d) >> 16), \ + (a[(n)+2] = (d) >> 8), \ + (a[(n)+3] = (d) & 255) + +#define GET(a,n) \ + (((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3]) + +/* Keep it positive */ +#define MAX_PATTERN_SIZE (1 << 30) + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + +#else /* COMPILE_PCRE8 */ + +#ifdef COMPILE_PCRE16 + +#if LINK_SIZE == 2 + +#undef LINK_SIZE +#define LINK_SIZE 1 + +#define PUT(a,n,d) \ + (a[n] = (d)) + +#define GET(a,n) \ + (a[n]) + +#define MAX_PATTERN_SIZE (1 << 16) + +#elif LINK_SIZE == 3 || LINK_SIZE == 4 + +#undef LINK_SIZE +#define LINK_SIZE 2 + +#define PUT(a,n,d) \ + (a[n] = (d) >> 16), \ + (a[(n)+1] = (d) & 65535) + +#define GET(a,n) \ + (((a)[n] << 16) | (a)[(n)+1]) + +/* Keep it positive */ +#define MAX_PATTERN_SIZE (1 << 30) + +#else +#error LINK_SIZE must be either 2, 3, or 4 +#endif + +#else +#error Unsupported compiling mode +#endif /* COMPILE_PCRE16 */ + +#endif /* COMPILE_PCRE8 */ + +/* Convenience macro defined in terms of the others */ + +#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE + + +/* PCRE uses some other 2-byte quantities that do not change when the size of +offsets changes. There are used for repeat counts and for other things such as +capturing parenthesis numbers in back references. */ + +#ifdef COMPILE_PCRE8 + +#define IMM2_SIZE 2 + +#define PUT2(a,n,d) \ + a[n] = (d) >> 8; \ + a[(n)+1] = (d) & 255 + +#define GET2(a,n) \ + (((a)[n] << 8) | (a)[(n)+1]) + +#else /* COMPILE_PCRE8 */ + +#ifdef COMPILE_PCRE16 + +#define IMM2_SIZE 1 + +#define PUT2(a,n,d) \ + a[n] = d + +#define GET2(a,n) \ + a[n] + +#else +#error Unsupported compiling mode +#endif /* COMPILE_PCRE16 */ + +#endif /* COMPILE_PCRE8 */ + +#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE + +/* When UTF encoding is being used, a character is no longer just a single +character. The macros for character handling generate simple sequences when +used in character-mode, and more complicated ones for UTF characters. +GETCHARLENTEST and other macros are not used when UTF is not supported, +so they are not defined. To make sure they can never even appear when +UTF support is omitted, we don't even define them. */ + +#ifndef SUPPORT_UTF + +/* #define MAX_VALUE_FOR_SINGLE_CHAR */ +/* #define HAS_EXTRALEN(c) */ +/* #define GET_EXTRALEN(c) */ +/* #define NOT_FIRSTCHAR(c) */ +#define GETCHAR(c, eptr) c = *eptr; +#define GETCHARTEST(c, eptr) c = *eptr; +#define GETCHARINC(c, eptr) c = *eptr++; +#define GETCHARINCTEST(c, eptr) c = *eptr++; +#define GETCHARLEN(c, eptr, len) c = *eptr; +/* #define GETCHARLENTEST(c, eptr, len) */ +/* #define BACKCHAR(eptr) */ +/* #define FORWARDCHAR(eptr) */ +/* #define ACROSSCHAR(condition, eptr, action) */ + +#else /* SUPPORT_UTF */ + +#ifdef COMPILE_PCRE8 + +/* These macros were originally written in the form of loops that used data +from the tables whose names start with PRIV(utf8_table). They were rewritten by +a user so as not to use loops, because in some environments this gives a +significant performance advantage, and it seems never to do any harm. */ + +/* Tells the biggest code point which can be encoded as a single character. */ + +#define MAX_VALUE_FOR_SINGLE_CHAR 127 + +/* Tests whether the code point needs extra characters to decode. */ + +#define HAS_EXTRALEN(c) ((c) >= 0xc0) + +/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. +Otherwise it has an undefined behaviour. */ + +#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3f]) + +/* Returns TRUE, if the given character is not the first character +of a UTF sequence. */ + +#define NOT_FIRSTCHAR(c) (((c) & 0xc0) == 0x80) + +/* Base macro to pick up the remaining bytes of a UTF-8 character, not +advancing the pointer. */ + +#define GETUTF8(c, eptr) \ + { \ + if ((c & 0x20) == 0) \ + c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ + else if ((c & 0x10) == 0) \ + c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ + else if ((c & 0x08) == 0) \ + c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ + ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ + else if ((c & 0x04) == 0) \ + c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ + ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ + (eptr[4] & 0x3f); \ + else \ + c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ + ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ + ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ + } + +/* Get the next UTF-8 character, not advancing the pointer. This is called when +we know we are in UTF-8 mode. */ + +#define GETCHAR(c, eptr) \ + c = *eptr; \ + if (c >= 0xc0) GETUTF8(c, eptr); + +/* Get the next UTF-8 character, testing for UTF-8 mode, and not advancing the +pointer. */ + +#define GETCHARTEST(c, eptr) \ + c = *eptr; \ + if (utf && c >= 0xc0) GETUTF8(c, eptr); + +/* Base macro to pick up the remaining bytes of a UTF-8 character, advancing +the pointer. */ + +#define GETUTF8INC(c, eptr) \ + { \ + if ((c & 0x20) == 0) \ + c = ((c & 0x1f) << 6) | (*eptr++ & 0x3f); \ + else if ((c & 0x10) == 0) \ + { \ + c = ((c & 0x0f) << 12) | ((*eptr & 0x3f) << 6) | (eptr[1] & 0x3f); \ + eptr += 2; \ + } \ + else if ((c & 0x08) == 0) \ + { \ + c = ((c & 0x07) << 18) | ((*eptr & 0x3f) << 12) | \ + ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ + eptr += 3; \ + } \ + else if ((c & 0x04) == 0) \ + { \ + c = ((c & 0x03) << 24) | ((*eptr & 0x3f) << 18) | \ + ((eptr[1] & 0x3f) << 12) | ((eptr[2] & 0x3f) << 6) | \ + (eptr[3] & 0x3f); \ + eptr += 4; \ + } \ + else \ + { \ + c = ((c & 0x01) << 30) | ((*eptr & 0x3f) << 24) | \ + ((eptr[1] & 0x3f) << 18) | ((eptr[2] & 0x3f) << 12) | \ + ((eptr[3] & 0x3f) << 6) | (eptr[4] & 0x3f); \ + eptr += 5; \ + } \ + } + +/* Get the next UTF-8 character, advancing the pointer. This is called when we +know we are in UTF-8 mode. */ + +#define GETCHARINC(c, eptr) \ + c = *eptr++; \ + if (c >= 0xc0) GETUTF8INC(c, eptr); + +/* Get the next character, testing for UTF-8 mode, and advancing the pointer. +This is called when we don't know if we are in UTF-8 mode. */ + +#define GETCHARINCTEST(c, eptr) \ + c = *eptr++; \ + if (utf && c >= 0xc0) GETUTF8INC(c, eptr); + +/* Base macro to pick up the remaining bytes of a UTF-8 character, not +advancing the pointer, incrementing the length. */ + +#define GETUTF8LEN(c, eptr, len) \ + { \ + if ((c & 0x20) == 0) \ + { \ + c = ((c & 0x1f) << 6) | (eptr[1] & 0x3f); \ + len++; \ + } \ + else if ((c & 0x10) == 0) \ + { \ + c = ((c & 0x0f) << 12) | ((eptr[1] & 0x3f) << 6) | (eptr[2] & 0x3f); \ + len += 2; \ + } \ + else if ((c & 0x08) == 0) \ + {\ + c = ((c & 0x07) << 18) | ((eptr[1] & 0x3f) << 12) | \ + ((eptr[2] & 0x3f) << 6) | (eptr[3] & 0x3f); \ + len += 3; \ + } \ + else if ((c & 0x04) == 0) \ + { \ + c = ((c & 0x03) << 24) | ((eptr[1] & 0x3f) << 18) | \ + ((eptr[2] & 0x3f) << 12) | ((eptr[3] & 0x3f) << 6) | \ + (eptr[4] & 0x3f); \ + len += 4; \ + } \ + else \ + {\ + c = ((c & 0x01) << 30) | ((eptr[1] & 0x3f) << 24) | \ + ((eptr[2] & 0x3f) << 18) | ((eptr[3] & 0x3f) << 12) | \ + ((eptr[4] & 0x3f) << 6) | (eptr[5] & 0x3f); \ + len += 5; \ + } \ + } + +/* Get the next UTF-8 character, not advancing the pointer, incrementing length +if there are extra bytes. This is called when we know we are in UTF-8 mode. */ + +#define GETCHARLEN(c, eptr, len) \ + c = *eptr; \ + if (c >= 0xc0) GETUTF8LEN(c, eptr, len); + +/* Get the next UTF-8 character, testing for UTF-8 mode, not advancing the +pointer, incrementing length if there are extra bytes. This is called when we +do not know if we are in UTF-8 mode. */ + +#define GETCHARLENTEST(c, eptr, len) \ + c = *eptr; \ + if (utf && c >= 0xc0) GETUTF8LEN(c, eptr, len); + +/* If the pointer is not at the start of a character, move it back until +it is. This is called only in UTF-8 mode - we don't put a test within the macro +because almost all calls are already within a block of UTF-8 only code. */ + +#define BACKCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr-- + +/* Same as above, just in the other direction. */ +#define FORWARDCHAR(eptr) while((*eptr & 0xc0) == 0x80) eptr++ + +/* Same as above, but it allows a fully customizable form. */ +#define ACROSSCHAR(condition, eptr, action) \ + while((condition) && ((eptr) & 0xc0) == 0x80) action + +#else /* COMPILE_PCRE8 */ + +#ifdef COMPILE_PCRE16 + +/* Tells the biggest code point which can be encoded as a single character. */ + +#define MAX_VALUE_FOR_SINGLE_CHAR 65535 + +/* Tests whether the code point needs extra characters to decode. */ + +#define HAS_EXTRALEN(c) (((c) & 0xfc00) == 0xd800) + +/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE. +Otherwise it has an undefined behaviour. */ + +#define GET_EXTRALEN(c) 1 + +/* Returns TRUE, if the given character is not the first character +of a UTF sequence. */ + +#define NOT_FIRSTCHAR(c) (((c) & 0xfc00) == 0xdc00) + +/* Base macro to pick up the low surrogate of a UTF-16 character, not +advancing the pointer. */ + +#define GETUTF16(c, eptr) \ + { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; } + +/* Get the next UTF-16 character, not advancing the pointer. This is called when +we know we are in UTF-16 mode. */ + +#define GETCHAR(c, eptr) \ + c = *eptr; \ + if ((c & 0xfc00) == 0xd800) GETUTF16(c, eptr); + +/* Get the next UTF-16 character, testing for UTF-16 mode, and not advancing the +pointer. */ + +#define GETCHARTEST(c, eptr) \ + c = *eptr; \ + if (utf && (c & 0xfc00) == 0xd800) GETUTF16(c, eptr); + +/* Base macro to pick up the low surrogate of a UTF-16 character, advancing +the pointer. */ + +#define GETUTF16INC(c, eptr) \ + { c = (((c & 0x3ff) << 10) | (*eptr++ & 0x3ff)) + 0x10000; } + +/* Get the next UTF-16 character, advancing the pointer. This is called when we +know we are in UTF-16 mode. */ + +#define GETCHARINC(c, eptr) \ + c = *eptr++; \ + if ((c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); + +/* Get the next character, testing for UTF-16 mode, and advancing the pointer. +This is called when we don't know if we are in UTF-16 mode. */ + +#define GETCHARINCTEST(c, eptr) \ + c = *eptr++; \ + if (utf && (c & 0xfc00) == 0xd800) GETUTF16INC(c, eptr); + +/* Base macro to pick up the low surrogate of a UTF-16 character, not +advancing the pointer, incrementing the length. */ + +#define GETUTF16LEN(c, eptr, len) \ + { c = (((c & 0x3ff) << 10) | (eptr[1] & 0x3ff)) + 0x10000; len++; } + +/* Get the next UTF-16 character, not advancing the pointer, incrementing +length if there is a low surrogate. This is called when we know we are in +UTF-16 mode. */ + +#define GETCHARLEN(c, eptr, len) \ + c = *eptr; \ + if ((c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); + +/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the +pointer, incrementing length if there is a low surrogate. This is called when +we do not know if we are in UTF-16 mode. */ + +#define GETCHARLENTEST(c, eptr, len) \ + c = *eptr; \ + if (utf && (c & 0xfc00) == 0xd800) GETUTF16LEN(c, eptr, len); + +/* If the pointer is not at the start of a character, move it back until +it is. This is called only in UTF-16 mode - we don't put a test within the +macro because almost all calls are already within a block of UTF-16 only +code. */ + +#define BACKCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr-- + +/* Same as above, just in the other direction. */ +#define FORWARDCHAR(eptr) if ((*eptr & 0xfc00) == 0xdc00) eptr++ + +/* Same as above, but it allows a fully customizable form. */ +#define ACROSSCHAR(condition, eptr, action) \ + if ((condition) && ((eptr) & 0xfc00) == 0xdc00) action + +#endif + +#endif /* COMPILE_PCRE8 */ + +#endif /* SUPPORT_UTF */ + + +/* In case there is no definition of offsetof() provided - though any proper +Standard C system should have one. */ + +#ifndef offsetof +#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field)) +#endif + + +/* Private flags containing information about the compiled regex. They used to +live at the top end of the options word, but that got almost full, so now they +are in a 16-bit flags word. From release 8.00, PCRE_NOPARTIAL is unused, as +the restrictions on partial matching have been lifted. It remains for backwards +compatibility. */ + +#ifdef COMPILE_PCRE8 +#define PCRE_MODE 0x0001 /* compiled in 8 bit mode */ +#endif +#ifdef COMPILE_PCRE16 +#define PCRE_MODE 0x0002 /* compiled in 16 bit mode */ +#endif +#define PCRE_FIRSTSET 0x0010 /* first_char is set */ +#define PCRE_FCH_CASELESS 0x0020 /* caseless first char */ +#define PCRE_REQCHSET 0x0040 /* req_byte is set */ +#define PCRE_RCH_CASELESS 0x0080 /* caseless requested char */ +#define PCRE_STARTLINE 0x0100 /* start after \n for multiline */ +#define PCRE_NOPARTIAL 0x0200 /* can't use partial with this regex */ +#define PCRE_JCHANGED 0x0400 /* j option used in regex */ +#define PCRE_HASCRORLF 0x0800 /* explicit \r or \n in pattern */ +#define PCRE_HASTHEN 0x1000 /* pattern contains (*THEN) */ + +/* Flags for the "extra" block produced by pcre_study(). */ + +#define PCRE_STUDY_MAPPED 0x0001 /* a map of starting chars exists */ +#define PCRE_STUDY_MINLEN 0x0002 /* a minimum length field exists */ + +/* Masks for identifying the public options that are permitted at compile +time, run time, or study time, respectively. */ + +#define PCRE_NEWLINE_BITS (PCRE_NEWLINE_CR|PCRE_NEWLINE_LF|PCRE_NEWLINE_ANY| \ + PCRE_NEWLINE_ANYCRLF) + +#define PUBLIC_COMPILE_OPTIONS \ + (PCRE_CASELESS|PCRE_EXTENDED|PCRE_ANCHORED|PCRE_MULTILINE| \ + PCRE_DOTALL|PCRE_DOLLAR_ENDONLY|PCRE_EXTRA|PCRE_UNGREEDY|PCRE_UTF8| \ + PCRE_NO_AUTO_CAPTURE|PCRE_NO_UTF8_CHECK|PCRE_AUTO_CALLOUT|PCRE_FIRSTLINE| \ + PCRE_DUPNAMES|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ + PCRE_JAVASCRIPT_COMPAT|PCRE_UCP|PCRE_NO_START_OPTIMIZE) + +#define PUBLIC_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ + PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_NEWLINE_BITS| \ + PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE|PCRE_NO_START_OPTIMIZE) + +#define PUBLIC_DFA_EXEC_OPTIONS \ + (PCRE_ANCHORED|PCRE_NOTBOL|PCRE_NOTEOL|PCRE_NOTEMPTY|PCRE_NOTEMPTY_ATSTART| \ + PCRE_NO_UTF8_CHECK|PCRE_PARTIAL_HARD|PCRE_PARTIAL_SOFT|PCRE_DFA_SHORTEST| \ + PCRE_DFA_RESTART|PCRE_NEWLINE_BITS|PCRE_BSR_ANYCRLF|PCRE_BSR_UNICODE| \ + PCRE_NO_START_OPTIMIZE) + +#define PUBLIC_STUDY_OPTIONS \ + PCRE_STUDY_JIT_COMPILE + +/* Magic number to provide a small check against being handed junk. */ + +#define MAGIC_NUMBER 0x50435245UL /* 'PCRE' */ + +/* This variable is used to detect a loaded regular expression +in different endianness. */ + +#define REVERSED_MAGIC_NUMBER 0x45524350UL /* 'ERCP' */ + +/* Negative values for the firstchar and reqchar variables */ + +#define REQ_UNSET (-2) +#define REQ_NONE (-1) + +/* The maximum remaining length of subject we are prepared to search for a +req_byte match. */ + +#define REQ_BYTE_MAX 1000 + +/* Miscellaneous definitions. The #ifndef is to pacify compiler warnings in +environments where these macros are defined elsewhere. Unfortunately, there +is no way to do the same for the typedef. */ + +typedef int BOOL; + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/* If PCRE is to support UTF-8 on EBCDIC platforms, we cannot use normal +character constants like '*' because the compiler would emit their EBCDIC code, +which is different from their ASCII/UTF-8 code. Instead we define macros for +the characters so that they always use the ASCII/UTF-8 code when UTF-8 support +is enabled. When UTF-8 support is not enabled, the definitions use character +literals. Both character and string versions of each character are needed, and +there are some longer strings as well. + +This means that, on EBCDIC platforms, the PCRE library can handle either +EBCDIC, or UTF-8, but not both. To support both in the same compiled library +would need different lookups depending on whether PCRE_UTF8 was set or not. +This would make it impossible to use characters in switch/case statements, +which would reduce performance. For a theoretical use (which nobody has asked +for) in a minority area (EBCDIC platforms), this is not sensible. Any +application that did need both could compile two versions of the library, using +macros to give the functions distinct names. */ + +#ifndef SUPPORT_UTF + +/* UTF-8 support is not enabled; use the platform-dependent character literals +so that PCRE works on both ASCII and EBCDIC platforms, in non-UTF-mode only. */ + +#define CHAR_HT '\t' +#define CHAR_VT '\v' +#define CHAR_FF '\f' +#define CHAR_CR '\r' +#define CHAR_NL '\n' +#define CHAR_BS '\b' +#define CHAR_BEL '\a' +#ifdef EBCDIC +#define CHAR_ESC '\047' +#define CHAR_DEL '\007' +#else +#define CHAR_ESC '\033' +#define CHAR_DEL '\177' +#endif + +#define CHAR_SPACE ' ' +#define CHAR_EXCLAMATION_MARK '!' +#define CHAR_QUOTATION_MARK '"' +#define CHAR_NUMBER_SIGN '#' +#define CHAR_DOLLAR_SIGN '$' +#define CHAR_PERCENT_SIGN '%' +#define CHAR_AMPERSAND '&' +#define CHAR_APOSTROPHE '\'' +#define CHAR_LEFT_PARENTHESIS '(' +#define CHAR_RIGHT_PARENTHESIS ')' +#define CHAR_ASTERISK '*' +#define CHAR_PLUS '+' +#define CHAR_COMMA ',' +#define CHAR_MINUS '-' +#define CHAR_DOT '.' +#define CHAR_SLASH '/' +#define CHAR_0 '0' +#define CHAR_1 '1' +#define CHAR_2 '2' +#define CHAR_3 '3' +#define CHAR_4 '4' +#define CHAR_5 '5' +#define CHAR_6 '6' +#define CHAR_7 '7' +#define CHAR_8 '8' +#define CHAR_9 '9' +#define CHAR_COLON ':' +#define CHAR_SEMICOLON ';' +#define CHAR_LESS_THAN_SIGN '<' +#define CHAR_EQUALS_SIGN '=' +#define CHAR_GREATER_THAN_SIGN '>' +#define CHAR_QUESTION_MARK '?' +#define CHAR_COMMERCIAL_AT '@' +#define CHAR_A 'A' +#define CHAR_B 'B' +#define CHAR_C 'C' +#define CHAR_D 'D' +#define CHAR_E 'E' +#define CHAR_F 'F' +#define CHAR_G 'G' +#define CHAR_H 'H' +#define CHAR_I 'I' +#define CHAR_J 'J' +#define CHAR_K 'K' +#define CHAR_L 'L' +#define CHAR_M 'M' +#define CHAR_N 'N' +#define CHAR_O 'O' +#define CHAR_P 'P' +#define CHAR_Q 'Q' +#define CHAR_R 'R' +#define CHAR_S 'S' +#define CHAR_T 'T' +#define CHAR_U 'U' +#define CHAR_V 'V' +#define CHAR_W 'W' +#define CHAR_X 'X' +#define CHAR_Y 'Y' +#define CHAR_Z 'Z' +#define CHAR_LEFT_SQUARE_BRACKET '[' +#define CHAR_BACKSLASH '\\' +#define CHAR_RIGHT_SQUARE_BRACKET ']' +#define CHAR_CIRCUMFLEX_ACCENT '^' +#define CHAR_UNDERSCORE '_' +#define CHAR_GRAVE_ACCENT '`' +#define CHAR_a 'a' +#define CHAR_b 'b' +#define CHAR_c 'c' +#define CHAR_d 'd' +#define CHAR_e 'e' +#define CHAR_f 'f' +#define CHAR_g 'g' +#define CHAR_h 'h' +#define CHAR_i 'i' +#define CHAR_j 'j' +#define CHAR_k 'k' +#define CHAR_l 'l' +#define CHAR_m 'm' +#define CHAR_n 'n' +#define CHAR_o 'o' +#define CHAR_p 'p' +#define CHAR_q 'q' +#define CHAR_r 'r' +#define CHAR_s 's' +#define CHAR_t 't' +#define CHAR_u 'u' +#define CHAR_v 'v' +#define CHAR_w 'w' +#define CHAR_x 'x' +#define CHAR_y 'y' +#define CHAR_z 'z' +#define CHAR_LEFT_CURLY_BRACKET '{' +#define CHAR_VERTICAL_LINE '|' +#define CHAR_RIGHT_CURLY_BRACKET '}' +#define CHAR_TILDE '~' + +#define STR_HT "\t" +#define STR_VT "\v" +#define STR_FF "\f" +#define STR_CR "\r" +#define STR_NL "\n" +#define STR_BS "\b" +#define STR_BEL "\a" +#ifdef EBCDIC +#define STR_ESC "\047" +#define STR_DEL "\007" +#else +#define STR_ESC "\033" +#define STR_DEL "\177" +#endif + +#define STR_SPACE " " +#define STR_EXCLAMATION_MARK "!" +#define STR_QUOTATION_MARK "\"" +#define STR_NUMBER_SIGN "#" +#define STR_DOLLAR_SIGN "$" +#define STR_PERCENT_SIGN "%" +#define STR_AMPERSAND "&" +#define STR_APOSTROPHE "'" +#define STR_LEFT_PARENTHESIS "(" +#define STR_RIGHT_PARENTHESIS ")" +#define STR_ASTERISK "*" +#define STR_PLUS "+" +#define STR_COMMA "," +#define STR_MINUS "-" +#define STR_DOT "." +#define STR_SLASH "/" +#define STR_0 "0" +#define STR_1 "1" +#define STR_2 "2" +#define STR_3 "3" +#define STR_4 "4" +#define STR_5 "5" +#define STR_6 "6" +#define STR_7 "7" +#define STR_8 "8" +#define STR_9 "9" +#define STR_COLON ":" +#define STR_SEMICOLON ";" +#define STR_LESS_THAN_SIGN "<" +#define STR_EQUALS_SIGN "=" +#define STR_GREATER_THAN_SIGN ">" +#define STR_QUESTION_MARK "?" +#define STR_COMMERCIAL_AT "@" +#define STR_A "A" +#define STR_B "B" +#define STR_C "C" +#define STR_D "D" +#define STR_E "E" +#define STR_F "F" +#define STR_G "G" +#define STR_H "H" +#define STR_I "I" +#define STR_J "J" +#define STR_K "K" +#define STR_L "L" +#define STR_M "M" +#define STR_N "N" +#define STR_O "O" +#define STR_P "P" +#define STR_Q "Q" +#define STR_R "R" +#define STR_S "S" +#define STR_T "T" +#define STR_U "U" +#define STR_V "V" +#define STR_W "W" +#define STR_X "X" +#define STR_Y "Y" +#define STR_Z "Z" +#define STR_LEFT_SQUARE_BRACKET "[" +#define STR_BACKSLASH "\\" +#define STR_RIGHT_SQUARE_BRACKET "]" +#define STR_CIRCUMFLEX_ACCENT "^" +#define STR_UNDERSCORE "_" +#define STR_GRAVE_ACCENT "`" +#define STR_a "a" +#define STR_b "b" +#define STR_c "c" +#define STR_d "d" +#define STR_e "e" +#define STR_f "f" +#define STR_g "g" +#define STR_h "h" +#define STR_i "i" +#define STR_j "j" +#define STR_k "k" +#define STR_l "l" +#define STR_m "m" +#define STR_n "n" +#define STR_o "o" +#define STR_p "p" +#define STR_q "q" +#define STR_r "r" +#define STR_s "s" +#define STR_t "t" +#define STR_u "u" +#define STR_v "v" +#define STR_w "w" +#define STR_x "x" +#define STR_y "y" +#define STR_z "z" +#define STR_LEFT_CURLY_BRACKET "{" +#define STR_VERTICAL_LINE "|" +#define STR_RIGHT_CURLY_BRACKET "}" +#define STR_TILDE "~" + +#define STRING_ACCEPT0 "ACCEPT\0" +#define STRING_COMMIT0 "COMMIT\0" +#define STRING_F0 "F\0" +#define STRING_FAIL0 "FAIL\0" +#define STRING_MARK0 "MARK\0" +#define STRING_PRUNE0 "PRUNE\0" +#define STRING_SKIP0 "SKIP\0" +#define STRING_THEN "THEN" + +#define STRING_alpha0 "alpha\0" +#define STRING_lower0 "lower\0" +#define STRING_upper0 "upper\0" +#define STRING_alnum0 "alnum\0" +#define STRING_ascii0 "ascii\0" +#define STRING_blank0 "blank\0" +#define STRING_cntrl0 "cntrl\0" +#define STRING_digit0 "digit\0" +#define STRING_graph0 "graph\0" +#define STRING_print0 "print\0" +#define STRING_punct0 "punct\0" +#define STRING_space0 "space\0" +#define STRING_word0 "word\0" +#define STRING_xdigit "xdigit" + +#define STRING_DEFINE "DEFINE" + +#define STRING_CR_RIGHTPAR "CR)" +#define STRING_LF_RIGHTPAR "LF)" +#define STRING_CRLF_RIGHTPAR "CRLF)" +#define STRING_ANY_RIGHTPAR "ANY)" +#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)" +#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)" +#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)" +#ifdef COMPILE_PCRE8 +#define STRING_UTF_RIGHTPAR "UTF8)" +#endif +#ifdef COMPILE_PCRE16 +#define STRING_UTF_RIGHTPAR "UTF16)" +#endif +#define STRING_UCP_RIGHTPAR "UCP)" +#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)" + +#else /* SUPPORT_UTF */ + +/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This +works in both modes non-EBCDIC platforms, and on EBCDIC platforms in UTF-8 mode +only. */ + +#define CHAR_HT '\011' +#define CHAR_VT '\013' +#define CHAR_FF '\014' +#define CHAR_CR '\015' +#define CHAR_NL '\012' +#define CHAR_BS '\010' +#define CHAR_BEL '\007' +#define CHAR_ESC '\033' +#define CHAR_DEL '\177' + +#define CHAR_SPACE '\040' +#define CHAR_EXCLAMATION_MARK '\041' +#define CHAR_QUOTATION_MARK '\042' +#define CHAR_NUMBER_SIGN '\043' +#define CHAR_DOLLAR_SIGN '\044' +#define CHAR_PERCENT_SIGN '\045' +#define CHAR_AMPERSAND '\046' +#define CHAR_APOSTROPHE '\047' +#define CHAR_LEFT_PARENTHESIS '\050' +#define CHAR_RIGHT_PARENTHESIS '\051' +#define CHAR_ASTERISK '\052' +#define CHAR_PLUS '\053' +#define CHAR_COMMA '\054' +#define CHAR_MINUS '\055' +#define CHAR_DOT '\056' +#define CHAR_SLASH '\057' +#define CHAR_0 '\060' +#define CHAR_1 '\061' +#define CHAR_2 '\062' +#define CHAR_3 '\063' +#define CHAR_4 '\064' +#define CHAR_5 '\065' +#define CHAR_6 '\066' +#define CHAR_7 '\067' +#define CHAR_8 '\070' +#define CHAR_9 '\071' +#define CHAR_COLON '\072' +#define CHAR_SEMICOLON '\073' +#define CHAR_LESS_THAN_SIGN '\074' +#define CHAR_EQUALS_SIGN '\075' +#define CHAR_GREATER_THAN_SIGN '\076' +#define CHAR_QUESTION_MARK '\077' +#define CHAR_COMMERCIAL_AT '\100' +#define CHAR_A '\101' +#define CHAR_B '\102' +#define CHAR_C '\103' +#define CHAR_D '\104' +#define CHAR_E '\105' +#define CHAR_F '\106' +#define CHAR_G '\107' +#define CHAR_H '\110' +#define CHAR_I '\111' +#define CHAR_J '\112' +#define CHAR_K '\113' +#define CHAR_L '\114' +#define CHAR_M '\115' +#define CHAR_N '\116' +#define CHAR_O '\117' +#define CHAR_P '\120' +#define CHAR_Q '\121' +#define CHAR_R '\122' +#define CHAR_S '\123' +#define CHAR_T '\124' +#define CHAR_U '\125' +#define CHAR_V '\126' +#define CHAR_W '\127' +#define CHAR_X '\130' +#define CHAR_Y '\131' +#define CHAR_Z '\132' +#define CHAR_LEFT_SQUARE_BRACKET '\133' +#define CHAR_BACKSLASH '\134' +#define CHAR_RIGHT_SQUARE_BRACKET '\135' +#define CHAR_CIRCUMFLEX_ACCENT '\136' +#define CHAR_UNDERSCORE '\137' +#define CHAR_GRAVE_ACCENT '\140' +#define CHAR_a '\141' +#define CHAR_b '\142' +#define CHAR_c '\143' +#define CHAR_d '\144' +#define CHAR_e '\145' +#define CHAR_f '\146' +#define CHAR_g '\147' +#define CHAR_h '\150' +#define CHAR_i '\151' +#define CHAR_j '\152' +#define CHAR_k '\153' +#define CHAR_l '\154' +#define CHAR_m '\155' +#define CHAR_n '\156' +#define CHAR_o '\157' +#define CHAR_p '\160' +#define CHAR_q '\161' +#define CHAR_r '\162' +#define CHAR_s '\163' +#define CHAR_t '\164' +#define CHAR_u '\165' +#define CHAR_v '\166' +#define CHAR_w '\167' +#define CHAR_x '\170' +#define CHAR_y '\171' +#define CHAR_z '\172' +#define CHAR_LEFT_CURLY_BRACKET '\173' +#define CHAR_VERTICAL_LINE '\174' +#define CHAR_RIGHT_CURLY_BRACKET '\175' +#define CHAR_TILDE '\176' + +#define STR_HT "\011" +#define STR_VT "\013" +#define STR_FF "\014" +#define STR_CR "\015" +#define STR_NL "\012" +#define STR_BS "\010" +#define STR_BEL "\007" +#define STR_ESC "\033" +#define STR_DEL "\177" + +#define STR_SPACE "\040" +#define STR_EXCLAMATION_MARK "\041" +#define STR_QUOTATION_MARK "\042" +#define STR_NUMBER_SIGN "\043" +#define STR_DOLLAR_SIGN "\044" +#define STR_PERCENT_SIGN "\045" +#define STR_AMPERSAND "\046" +#define STR_APOSTROPHE "\047" +#define STR_LEFT_PARENTHESIS "\050" +#define STR_RIGHT_PARENTHESIS "\051" +#define STR_ASTERISK "\052" +#define STR_PLUS "\053" +#define STR_COMMA "\054" +#define STR_MINUS "\055" +#define STR_DOT "\056" +#define STR_SLASH "\057" +#define STR_0 "\060" +#define STR_1 "\061" +#define STR_2 "\062" +#define STR_3 "\063" +#define STR_4 "\064" +#define STR_5 "\065" +#define STR_6 "\066" +#define STR_7 "\067" +#define STR_8 "\070" +#define STR_9 "\071" +#define STR_COLON "\072" +#define STR_SEMICOLON "\073" +#define STR_LESS_THAN_SIGN "\074" +#define STR_EQUALS_SIGN "\075" +#define STR_GREATER_THAN_SIGN "\076" +#define STR_QUESTION_MARK "\077" +#define STR_COMMERCIAL_AT "\100" +#define STR_A "\101" +#define STR_B "\102" +#define STR_C "\103" +#define STR_D "\104" +#define STR_E "\105" +#define STR_F "\106" +#define STR_G "\107" +#define STR_H "\110" +#define STR_I "\111" +#define STR_J "\112" +#define STR_K "\113" +#define STR_L "\114" +#define STR_M "\115" +#define STR_N "\116" +#define STR_O "\117" +#define STR_P "\120" +#define STR_Q "\121" +#define STR_R "\122" +#define STR_S "\123" +#define STR_T "\124" +#define STR_U "\125" +#define STR_V "\126" +#define STR_W "\127" +#define STR_X "\130" +#define STR_Y "\131" +#define STR_Z "\132" +#define STR_LEFT_SQUARE_BRACKET "\133" +#define STR_BACKSLASH "\134" +#define STR_RIGHT_SQUARE_BRACKET "\135" +#define STR_CIRCUMFLEX_ACCENT "\136" +#define STR_UNDERSCORE "\137" +#define STR_GRAVE_ACCENT "\140" +#define STR_a "\141" +#define STR_b "\142" +#define STR_c "\143" +#define STR_d "\144" +#define STR_e "\145" +#define STR_f "\146" +#define STR_g "\147" +#define STR_h "\150" +#define STR_i "\151" +#define STR_j "\152" +#define STR_k "\153" +#define STR_l "\154" +#define STR_m "\155" +#define STR_n "\156" +#define STR_o "\157" +#define STR_p "\160" +#define STR_q "\161" +#define STR_r "\162" +#define STR_s "\163" +#define STR_t "\164" +#define STR_u "\165" +#define STR_v "\166" +#define STR_w "\167" +#define STR_x "\170" +#define STR_y "\171" +#define STR_z "\172" +#define STR_LEFT_CURLY_BRACKET "\173" +#define STR_VERTICAL_LINE "\174" +#define STR_RIGHT_CURLY_BRACKET "\175" +#define STR_TILDE "\176" + +#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0" +#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0" +#define STRING_F0 STR_F "\0" +#define STRING_FAIL0 STR_F STR_A STR_I STR_L "\0" +#define STRING_MARK0 STR_M STR_A STR_R STR_K "\0" +#define STRING_PRUNE0 STR_P STR_R STR_U STR_N STR_E "\0" +#define STRING_SKIP0 STR_S STR_K STR_I STR_P "\0" +#define STRING_THEN STR_T STR_H STR_E STR_N + +#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0" +#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0" +#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0" +#define STRING_alnum0 STR_a STR_l STR_n STR_u STR_m "\0" +#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0" +#define STRING_blank0 STR_b STR_l STR_a STR_n STR_k "\0" +#define STRING_cntrl0 STR_c STR_n STR_t STR_r STR_l "\0" +#define STRING_digit0 STR_d STR_i STR_g STR_i STR_t "\0" +#define STRING_graph0 STR_g STR_r STR_a STR_p STR_h "\0" +#define STRING_print0 STR_p STR_r STR_i STR_n STR_t "\0" +#define STRING_punct0 STR_p STR_u STR_n STR_c STR_t "\0" +#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0" +#define STRING_word0 STR_w STR_o STR_r STR_d "\0" +#define STRING_xdigit STR_x STR_d STR_i STR_g STR_i STR_t + +#define STRING_DEFINE STR_D STR_E STR_F STR_I STR_N STR_E + +#define STRING_CR_RIGHTPAR STR_C STR_R STR_RIGHT_PARENTHESIS +#define STRING_LF_RIGHTPAR STR_L STR_F STR_RIGHT_PARENTHESIS +#define STRING_CRLF_RIGHTPAR STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS +#define STRING_ANY_RIGHTPAR STR_A STR_N STR_Y STR_RIGHT_PARENTHESIS +#define STRING_ANYCRLF_RIGHTPAR STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS +#define STRING_BSR_ANYCRLF_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_A STR_N STR_Y STR_C STR_R STR_L STR_F STR_RIGHT_PARENTHESIS +#define STRING_BSR_UNICODE_RIGHTPAR STR_B STR_S STR_R STR_UNDERSCORE STR_U STR_N STR_I STR_C STR_O STR_D STR_E STR_RIGHT_PARENTHESIS +#ifdef COMPILE_PCRE8 +#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_8 STR_RIGHT_PARENTHESIS +#endif +#ifdef COMPILE_PCRE16 +#define STRING_UTF_RIGHTPAR STR_U STR_T STR_F STR_1 STR_6 STR_RIGHT_PARENTHESIS +#endif +#define STRING_UCP_RIGHTPAR STR_U STR_C STR_P STR_RIGHT_PARENTHESIS +#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS + +#endif /* SUPPORT_UTF */ + +/* Escape items that are just an encoding of a particular data value. */ + +#ifndef ESC_e +#define ESC_e CHAR_ESC +#endif + +#ifndef ESC_f +#define ESC_f CHAR_FF +#endif + +#ifndef ESC_n +#define ESC_n CHAR_NL +#endif + +#ifndef ESC_r +#define ESC_r CHAR_CR +#endif + +/* We can't officially use ESC_t because it is a POSIX reserved identifier +(presumably because of all the others like size_t). */ + +#ifndef ESC_tee +#define ESC_tee CHAR_HT +#endif + +/* Codes for different types of Unicode property */ + +#define PT_ANY 0 /* Any property - matches all chars */ +#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */ +#define PT_GC 2 /* Specified general characteristic (e.g. L) */ +#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */ +#define PT_SC 4 /* Script (e.g. Han) */ +#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */ +#define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */ +#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */ +#define PT_WORD 8 /* Word - L plus N plus underscore */ + +/* Flag bits and data types for the extended class (OP_XCLASS) for classes that +contain characters with values greater than 255. */ + +#define XCL_NOT 0x01 /* Flag: this is a negative class */ +#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */ + +#define XCL_END 0 /* Marks end of individual items */ +#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */ +#define XCL_RANGE 2 /* A range (two multibyte chars) follows */ +#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */ +#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */ + +/* These are escaped items that aren't just an encoding of a particular data +value such as \n. They must have non-zero values, as check_escape() returns +their negation. Also, they must appear in the same order as in the opcode +definitions below, up to ESC_z. There's a dummy for OP_ALLANY because it +corresponds to "." in DOTALL mode rather than an escape sequence. It is also +used for [^] in JavaScript compatibility mode, and for \C in non-utf mode. In +non-DOTALL mode, "." behaves like \N. + +The special values ESC_DU, ESC_du, etc. are used instead of ESC_D, ESC_d, etc. +when PCRE_UCP is set, when replacement of \d etc by \p sequences is required. +They must be contiguous, and remain in order so that the replacements can be +looked up from a table. + +The final escape must be ESC_REF as subsequent values are used for +backreferences (\1, \2, \3, etc). There are two tests in the code for an escape +greater than ESC_b and less than ESC_Z to detect the types that may be +repeated. These are the types that consume characters. If any new escapes are +put in between that don't consume a character, that code will have to change. +*/ + +enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, + ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H, + ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z, + ESC_E, ESC_Q, ESC_g, ESC_k, + ESC_DU, ESC_du, ESC_SU, ESC_su, ESC_WU, ESC_wu, + ESC_REF }; + +/* Opcode table: Starting from 1 (i.e. after OP_END), the values up to +OP_EOD must correspond in order to the list of escapes immediately above. + +*** NOTE NOTE NOTE *** Whenever this list is updated, the two macro definitions +that follow must also be updated to match. There are also tables called +"coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */ + +enum { + OP_END, /* 0 End of pattern */ + + /* Values corresponding to backslashed metacharacters */ + + OP_SOD, /* 1 Start of data: \A */ + OP_SOM, /* 2 Start of match (subject + offset): \G */ + OP_SET_SOM, /* 3 Set start of match (\K) */ + OP_NOT_WORD_BOUNDARY, /* 4 \B */ + OP_WORD_BOUNDARY, /* 5 \b */ + OP_NOT_DIGIT, /* 6 \D */ + OP_DIGIT, /* 7 \d */ + OP_NOT_WHITESPACE, /* 8 \S */ + OP_WHITESPACE, /* 9 \s */ + OP_NOT_WORDCHAR, /* 10 \W */ + OP_WORDCHAR, /* 11 \w */ + + OP_ANY, /* 12 Match any character except newline */ + OP_ALLANY, /* 13 Match any character */ + OP_ANYBYTE, /* 14 Match any byte (\C); different to OP_ANY for UTF-8 */ + OP_NOTPROP, /* 15 \P (not Unicode property) */ + OP_PROP, /* 16 \p (Unicode property) */ + OP_ANYNL, /* 17 \R (any newline sequence) */ + OP_NOT_HSPACE, /* 18 \H (not horizontal whitespace) */ + OP_HSPACE, /* 19 \h (horizontal whitespace) */ + OP_NOT_VSPACE, /* 20 \V (not vertical whitespace) */ + OP_VSPACE, /* 21 \v (vertical whitespace) */ + OP_EXTUNI, /* 22 \X (extended Unicode sequence */ + OP_EODN, /* 23 End of data or \n at end of data: \Z. */ + OP_EOD, /* 24 End of data: \z */ + + OP_CIRC, /* 25 Start of line - not multiline */ + OP_CIRCM, /* 26 Start of line - multiline */ + OP_DOLL, /* 27 End of line - not multiline */ + OP_DOLLM, /* 28 End of line - multiline */ + OP_CHAR, /* 29 Match one character, casefully */ + OP_CHARI, /* 30 Match one character, caselessly */ + OP_NOT, /* 31 Match one character, not the given one, casefully */ + OP_NOTI, /* 32 Match one character, not the given one, caselessly */ + + /* The following sets of 13 opcodes must always be kept in step because + the offset from the first one is used to generate the others. */ + + /**** Single characters, caseful, must precede the caseless ones ****/ + + OP_STAR, /* 33 The maximizing and minimizing versions of */ + OP_MINSTAR, /* 34 these six opcodes must come in pairs, with */ + OP_PLUS, /* 35 the minimizing one second. */ + OP_MINPLUS, /* 36 */ + OP_QUERY, /* 37 */ + OP_MINQUERY, /* 38 */ + + OP_UPTO, /* 39 From 0 to n matches of one character, caseful*/ + OP_MINUPTO, /* 40 */ + OP_EXACT, /* 41 Exactly n matches */ + + OP_POSSTAR, /* 42 Possessified star, caseful */ + OP_POSPLUS, /* 43 Possessified plus, caseful */ + OP_POSQUERY, /* 44 Posesssified query, caseful */ + OP_POSUPTO, /* 45 Possessified upto, caseful */ + + /**** Single characters, caseless, must follow the caseful ones */ + + OP_STARI, /* 46 */ + OP_MINSTARI, /* 47 */ + OP_PLUSI, /* 48 */ + OP_MINPLUSI, /* 49 */ + OP_QUERYI, /* 50 */ + OP_MINQUERYI, /* 51 */ + + OP_UPTOI, /* 52 From 0 to n matches of one character, caseless */ + OP_MINUPTOI, /* 53 */ + OP_EXACTI, /* 54 */ + + OP_POSSTARI, /* 55 Possessified star, caseless */ + OP_POSPLUSI, /* 56 Possessified plus, caseless */ + OP_POSQUERYI, /* 57 Posesssified query, caseless */ + OP_POSUPTOI, /* 58 Possessified upto, caseless */ + + /**** The negated ones must follow the non-negated ones, and match them ****/ + /**** Negated single character, caseful; must precede the caseless ones ****/ + + OP_NOTSTAR, /* 59 The maximizing and minimizing versions of */ + OP_NOTMINSTAR, /* 60 these six opcodes must come in pairs, with */ + OP_NOTPLUS, /* 61 the minimizing one second. They must be in */ + OP_NOTMINPLUS, /* 62 exactly the same order as those above. */ + OP_NOTQUERY, /* 63 */ + OP_NOTMINQUERY, /* 64 */ + + OP_NOTUPTO, /* 65 From 0 to n matches, caseful */ + OP_NOTMINUPTO, /* 66 */ + OP_NOTEXACT, /* 67 Exactly n matches */ + + OP_NOTPOSSTAR, /* 68 Possessified versions, caseful */ + OP_NOTPOSPLUS, /* 69 */ + OP_NOTPOSQUERY, /* 70 */ + OP_NOTPOSUPTO, /* 71 */ + + /**** Negated single character, caseless; must follow the caseful ones ****/ + + OP_NOTSTARI, /* 72 */ + OP_NOTMINSTARI, /* 73 */ + OP_NOTPLUSI, /* 74 */ + OP_NOTMINPLUSI, /* 75 */ + OP_NOTQUERYI, /* 76 */ + OP_NOTMINQUERYI, /* 77 */ + + OP_NOTUPTOI, /* 78 From 0 to n matches, caseless */ + OP_NOTMINUPTOI, /* 79 */ + OP_NOTEXACTI, /* 80 Exactly n matches */ + + OP_NOTPOSSTARI, /* 81 Possessified versions, caseless */ + OP_NOTPOSPLUSI, /* 82 */ + OP_NOTPOSQUERYI, /* 83 */ + OP_NOTPOSUPTOI, /* 84 */ + + /**** Character types ****/ + + OP_TYPESTAR, /* 85 The maximizing and minimizing versions of */ + OP_TYPEMINSTAR, /* 86 these six opcodes must come in pairs, with */ + OP_TYPEPLUS, /* 87 the minimizing one second. These codes must */ + OP_TYPEMINPLUS, /* 88 be in exactly the same order as those above. */ + OP_TYPEQUERY, /* 89 */ + OP_TYPEMINQUERY, /* 90 */ + + OP_TYPEUPTO, /* 91 From 0 to n matches */ + OP_TYPEMINUPTO, /* 92 */ + OP_TYPEEXACT, /* 93 Exactly n matches */ + + OP_TYPEPOSSTAR, /* 94 Possessified versions */ + OP_TYPEPOSPLUS, /* 95 */ + OP_TYPEPOSQUERY, /* 96 */ + OP_TYPEPOSUPTO, /* 97 */ + + /* These are used for character classes and back references; only the + first six are the same as the sets above. */ + + OP_CRSTAR, /* 98 The maximizing and minimizing versions of */ + OP_CRMINSTAR, /* 99 all these opcodes must come in pairs, with */ + OP_CRPLUS, /* 100 the minimizing one second. These codes must */ + OP_CRMINPLUS, /* 101 be in exactly the same order as those above. */ + OP_CRQUERY, /* 102 */ + OP_CRMINQUERY, /* 103 */ + + OP_CRRANGE, /* 104 These are different to the three sets above. */ + OP_CRMINRANGE, /* 105 */ + + /* End of quantifier opcodes */ + + OP_CLASS, /* 106 Match a character class, chars < 256 only */ + OP_NCLASS, /* 107 Same, but the bitmap was created from a negative + class - the difference is relevant only when a + character > 255 is encountered. */ + OP_XCLASS, /* 108 Extended class for handling > 255 chars within the + class. This does both positive and negative. */ + OP_REF, /* 109 Match a back reference, casefully */ + OP_REFI, /* 110 Match a back reference, caselessly */ + OP_RECURSE, /* 111 Match a numbered subpattern (possibly recursive) */ + OP_CALLOUT, /* 112 Call out to external function if provided */ + + OP_ALT, /* 113 Start of alternation */ + OP_KET, /* 114 End of group that doesn't have an unbounded repeat */ + OP_KETRMAX, /* 115 These two must remain together and in this */ + OP_KETRMIN, /* 116 order. They are for groups the repeat for ever. */ + OP_KETRPOS, /* 117 Possessive unlimited repeat. */ + + /* The assertions must come before BRA, CBRA, ONCE, and COND, and the four + asserts must remain in order. */ + + OP_REVERSE, /* 118 Move pointer back - used in lookbehind assertions */ + OP_ASSERT, /* 119 Positive lookahead */ + OP_ASSERT_NOT, /* 120 Negative lookahead */ + OP_ASSERTBACK, /* 121 Positive lookbehind */ + OP_ASSERTBACK_NOT, /* 122 Negative lookbehind */ + + /* ONCE, ONCE_NC, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come immediately + after the assertions, with ONCE first, as there's a test for >= ONCE for a + subpattern that isn't an assertion. The POS versions must immediately follow + the non-POS versions in each case. */ + + OP_ONCE, /* 123 Atomic group, contains captures */ + OP_ONCE_NC, /* 124 Atomic group containing no captures */ + OP_BRA, /* 125 Start of non-capturing bracket */ + OP_BRAPOS, /* 126 Ditto, with unlimited, possessive repeat */ + OP_CBRA, /* 127 Start of capturing bracket */ + OP_CBRAPOS, /* 128 Ditto, with unlimited, possessive repeat */ + OP_COND, /* 129 Conditional group */ + + /* These five must follow the previous five, in the same order. There's a + check for >= SBRA to distinguish the two sets. */ + + OP_SBRA, /* 130 Start of non-capturing bracket, check empty */ + OP_SBRAPOS, /* 131 Ditto, with unlimited, possessive repeat */ + OP_SCBRA, /* 132 Start of capturing bracket, check empty */ + OP_SCBRAPOS, /* 133 Ditto, with unlimited, possessive repeat */ + OP_SCOND, /* 134 Conditional group, check empty */ + + /* The next two pairs must (respectively) be kept together. */ + + OP_CREF, /* 135 Used to hold a capture number as condition */ + OP_NCREF, /* 136 Same, but generated by a name reference*/ + OP_RREF, /* 137 Used to hold a recursion number as condition */ + OP_NRREF, /* 138 Same, but generated by a name reference*/ + OP_DEF, /* 139 The DEFINE condition */ + + OP_BRAZERO, /* 140 These two must remain together and in this */ + OP_BRAMINZERO, /* 141 order. */ + OP_BRAPOSZERO, /* 142 */ + + /* These are backtracking control verbs */ + + OP_MARK, /* 143 always has an argument */ + OP_PRUNE, /* 144 */ + OP_PRUNE_ARG, /* 145 same, but with argument */ + OP_SKIP, /* 146 */ + OP_SKIP_ARG, /* 147 same, but with argument */ + OP_THEN, /* 148 */ + OP_THEN_ARG, /* 149 same, but with argument */ + OP_COMMIT, /* 150 */ + + /* These are forced failure and success verbs */ + + OP_FAIL, /* 151 */ + OP_ACCEPT, /* 152 */ + OP_ASSERT_ACCEPT, /* 153 Used inside assertions */ + OP_CLOSE, /* 154 Used before OP_ACCEPT to close open captures */ + + /* This is used to skip a subpattern with a {0} quantifier */ + + OP_SKIPZERO, /* 155 */ + + /* This is not an opcode, but is used to check that tables indexed by opcode + are the correct length, in order to catch updating errors - there have been + some in the past. */ + + OP_TABLE_LENGTH +}; + +/* *** NOTE NOTE NOTE *** Whenever the list above is updated, the two macro +definitions that follow must also be updated to match. There are also tables +called "coptable" and "poptable" in pcre_dfa_exec.c that must be updated. */ + + +/* This macro defines textual names for all the opcodes. These are used only +for debugging, and some of them are only partial names. The macro is referenced +only in pcre_printint.c, which fills out the full names in many cases (and in +some cases doesn't actually use these names at all). */ + +#define OP_NAME_LIST \ + "End", "\\A", "\\G", "\\K", "\\B", "\\b", "\\D", "\\d", \ + "\\S", "\\s", "\\W", "\\w", "Any", "AllAny", "Anybyte", \ + "notprop", "prop", "\\R", "\\H", "\\h", "\\V", "\\v", \ + "extuni", "\\Z", "\\z", \ + "^", "^", "$", "$", "char", "chari", "not", "noti", \ + "*", "*?", "+", "+?", "?", "??", \ + "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", \ + "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", \ + "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", \ + "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", "{", \ + "*+","++", "?+", "{", \ + "*", "*?", "+", "+?", "?", "??", "{", "{", \ + "class", "nclass", "xclass", "Ref", "Refi", \ + "Recurse", "Callout", \ + "Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \ + "Reverse", "Assert", "Assert not", "AssertB", "AssertB not", \ + "Once", "Once_NC", \ + "Bra", "BraPos", "CBra", "CBraPos", \ + "Cond", \ + "SBra", "SBraPos", "SCBra", "SCBraPos", \ + "SCond", \ + "Cond ref", "Cond nref", "Cond rec", "Cond nrec", "Cond def", \ + "Brazero", "Braminzero", "Braposzero", \ + "*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \ + "*THEN", "*THEN", "*COMMIT", "*FAIL", \ + "*ACCEPT", "*ASSERT_ACCEPT", \ + "Close", "Skip zero" + + +/* This macro defines the length of fixed length operations in the compiled +regex. The lengths are used when searching for specific things, and also in the +debugging printing of a compiled regex. We use a macro so that it can be +defined close to the definitions of the opcodes themselves. + +As things have been extended, some of these are no longer fixed lenths, but are +minima instead. For example, the length of a single-character repeat may vary +in UTF-8 mode. The code that uses this table must know about such things. */ + +#define OP_LENGTHS \ + 1, /* End */ \ + 1, 1, 1, 1, 1, /* \A, \G, \K, \B, \b */ \ + 1, 1, 1, 1, 1, 1, /* \D, \d, \S, \s, \W, \w */ \ + 1, 1, 1, /* Any, AllAny, Anybyte */ \ + 3, 3, /* \P, \p */ \ + 1, 1, 1, 1, 1, /* \R, \H, \h, \V, \v */ \ + 1, /* \X */ \ + 1, 1, 1, 1, 1, 1, /* \Z, \z, ^, ^M, $, $M */ \ + 2, /* Char - the minimum length */ \ + 2, /* Chari - the minimum length */ \ + 2, /* not */ \ + 2, /* noti */ \ + /* Positive single-char repeats ** These are */ \ + 2, 2, 2, 2, 2, 2, /* *, *?, +, +?, ?, ?? ** minima in */ \ + 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto, minupto ** mode */ \ + 2+IMM2_SIZE, /* exact */ \ + 2, 2, 2, 2+IMM2_SIZE, /* *+, ++, ?+, upto+ */ \ + 2, 2, 2, 2, 2, 2, /* *I, *?I, +I, +?I, ?I, ??I ** UTF-8 */ \ + 2+IMM2_SIZE, 2+IMM2_SIZE, /* upto I, minupto I */ \ + 2+IMM2_SIZE, /* exact I */ \ + 2, 2, 2, 2+IMM2_SIZE, /* *+I, ++I, ?+I, upto+I */ \ + /* Negative single-char repeats - only for chars < 256 */ \ + 2, 2, 2, 2, 2, 2, /* NOT *, *?, +, +?, ?, ?? */ \ + 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto, minupto */ \ + 2+IMM2_SIZE, /* NOT exact */ \ + 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *, +, ?, upto */ \ + 2, 2, 2, 2, 2, 2, /* NOT *I, *?I, +I, +?I, ?I, ??I */ \ + 2+IMM2_SIZE, 2+IMM2_SIZE, /* NOT upto I, minupto I */ \ + 2+IMM2_SIZE, /* NOT exact I */ \ + 2, 2, 2, 2+IMM2_SIZE, /* Possessive NOT *I, +I, ?I, upto I */ \ + /* Positive type repeats */ \ + 2, 2, 2, 2, 2, 2, /* Type *, *?, +, +?, ?, ?? */ \ + 2+IMM2_SIZE, 2+IMM2_SIZE, /* Type upto, minupto */ \ + 2+IMM2_SIZE, /* Type exact */ \ + 2, 2, 2, 2+IMM2_SIZE, /* Possessive *+, ++, ?+, upto+ */ \ + /* Character class & ref repeats */ \ + 1, 1, 1, 1, 1, 1, /* *, *?, +, +?, ?, ?? */ \ + 1+2*IMM2_SIZE, 1+2*IMM2_SIZE, /* CRRANGE, CRMINRANGE */ \ + 1+(32/sizeof(pcre_uchar)), /* CLASS */ \ + 1+(32/sizeof(pcre_uchar)), /* NCLASS */ \ + 0, /* XCLASS - variable length */ \ + 1+IMM2_SIZE, /* REF */ \ + 1+IMM2_SIZE, /* REFI */ \ + 1+LINK_SIZE, /* RECURSE */ \ + 2+2*LINK_SIZE, /* CALLOUT */ \ + 1+LINK_SIZE, /* Alt */ \ + 1+LINK_SIZE, /* Ket */ \ + 1+LINK_SIZE, /* KetRmax */ \ + 1+LINK_SIZE, /* KetRmin */ \ + 1+LINK_SIZE, /* KetRpos */ \ + 1+LINK_SIZE, /* Reverse */ \ + 1+LINK_SIZE, /* Assert */ \ + 1+LINK_SIZE, /* Assert not */ \ + 1+LINK_SIZE, /* Assert behind */ \ + 1+LINK_SIZE, /* Assert behind not */ \ + 1+LINK_SIZE, /* ONCE */ \ + 1+LINK_SIZE, /* ONCE_NC */ \ + 1+LINK_SIZE, /* BRA */ \ + 1+LINK_SIZE, /* BRAPOS */ \ + 1+LINK_SIZE+IMM2_SIZE, /* CBRA */ \ + 1+LINK_SIZE+IMM2_SIZE, /* CBRAPOS */ \ + 1+LINK_SIZE, /* COND */ \ + 1+LINK_SIZE, /* SBRA */ \ + 1+LINK_SIZE, /* SBRAPOS */ \ + 1+LINK_SIZE+IMM2_SIZE, /* SCBRA */ \ + 1+LINK_SIZE+IMM2_SIZE, /* SCBRAPOS */ \ + 1+LINK_SIZE, /* SCOND */ \ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* CREF, NCREF */ \ + 1+IMM2_SIZE, 1+IMM2_SIZE, /* RREF, NRREF */ \ + 1, /* DEF */ \ + 1, 1, 1, /* BRAZERO, BRAMINZERO, BRAPOSZERO */ \ + 3, 1, 3, /* MARK, PRUNE, PRUNE_ARG */ \ + 1, 3, /* SKIP, SKIP_ARG */ \ + 1, 3, /* THEN, THEN_ARG */ \ + 1, 1, 1, 1, /* COMMIT, FAIL, ACCEPT, ASSERT_ACCEPT */ \ + 1+IMM2_SIZE, 1 /* CLOSE, SKIPZERO */ + +/* A magic value for OP_RREF and OP_NRREF to indicate the "any recursion" +condition. */ + +#define RREF_ANY 0xffff + +/* Compile time error code numbers. They are given names so that they can more +easily be tracked. When a new number is added, the table called eint in +pcreposix.c must be updated. */ + +enum { ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, + ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, + ERR20, ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, + ERR30, ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, + ERR40, ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, + ERR50, ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, + ERR60, ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, + ERR70, ERR71, ERR72, ERR73, ERR74, ERRCOUNT }; + +/* The real format of the start of the pcre block; the index of names and the +code vector run on as long as necessary after the end. We store an explicit +offset to the name table so that if a regex is compiled on one host, saved, and +then run on another where the size of pointers is different, all might still +be well. For the case of compiled-on-4 and run-on-8, we include an extra +pointer that is always NULL. For future-proofing, a few dummy fields were +originally included - even though you can never get this planning right - but +there is only one left now. + +NOTE NOTE NOTE: +Because people can now save and re-use compiled patterns, any additions to this +structure should be made at the end, and something earlier (e.g. a new +flag in the options or one of the dummy fields) should indicate that the new +fields are present. Currently PCRE always sets the dummy fields to zero. +NOTE NOTE NOTE +*/ + +#ifdef COMPILE_PCRE8 +#define REAL_PCRE real_pcre +#else +#define REAL_PCRE real_pcre16 +#endif + +typedef struct REAL_PCRE { + pcre_uint32 magic_number; + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 options; /* Public options */ + pcre_uint16 flags; /* Private flags */ + pcre_uint16 dummy1; /* For future use */ + pcre_uint16 top_bracket; + pcre_uint16 top_backref; + pcre_uint16 first_char; /* Starting character */ + pcre_uint16 req_char; /* This character must be seen */ + pcre_uint16 name_table_offset; /* Offset to name table that follows */ + pcre_uint16 name_entry_size; /* Size of any name items */ + pcre_uint16 name_count; /* Number of name items */ + pcre_uint16 ref_count; /* Reference count */ + + const pcre_uint8 *tables; /* Pointer to tables or NULL for std */ + const pcre_uint8 *nullpad; /* NULL padding */ +} REAL_PCRE; + +/* The format of the block used to store data from pcre_study(). The same +remark (see NOTE above) about extending this structure applies. */ + +typedef struct pcre_study_data { + pcre_uint32 size; /* Total that was malloced */ + pcre_uint32 flags; /* Private flags */ + pcre_uint8 start_bits[32]; /* Starting char bits */ + pcre_uint32 minlength; /* Minimum subject length */ +} pcre_study_data; + +/* Structure for building a chain of open capturing subpatterns during +compiling, so that instructions to close them can be compiled when (*ACCEPT) is +encountered. This is also used to identify subpatterns that contain recursive +back references to themselves, so that they can be made atomic. */ + +typedef struct open_capitem { + struct open_capitem *next; /* Chain link */ + pcre_uint16 number; /* Capture number */ + pcre_uint16 flag; /* Set TRUE if recursive back ref */ +} open_capitem; + +/* Structure for passing "static" information around between the functions +doing the compiling, so that they are thread-safe. */ + +typedef struct compile_data { + const pcre_uint8 *lcc; /* Points to lower casing table */ + const pcre_uint8 *fcc; /* Points to case-flipping table */ + const pcre_uint8 *cbits; /* Points to character type table */ + const pcre_uint8 *ctypes; /* Points to table of type maps */ + const pcre_uchar *start_workspace;/* The start of working space */ + const pcre_uchar *start_code; /* The start of the compiled code */ + const pcre_uchar *start_pattern; /* The start of the pattern */ + const pcre_uchar *end_pattern; /* The end of the pattern */ + open_capitem *open_caps; /* Chain of open capture items */ + pcre_uchar *hwm; /* High watermark of workspace */ + pcre_uchar *name_table; /* The name/number table */ + int names_found; /* Number of entries so far */ + int name_entry_size; /* Size of each entry */ + int workspace_size; /* Size of workspace */ + int bracount; /* Count of capturing parens as we compile */ + int final_bracount; /* Saved value after first pass */ + int top_backref; /* Maximum back reference */ + unsigned int backref_map; /* Bitmap of low back refs */ + int assert_depth; /* Depth of nested assertions */ + int external_options; /* External (initial) options */ + int external_flags; /* External flag bits to be set */ + int req_varyopt; /* "After variable item" flag for reqbyte */ + BOOL had_accept; /* (*ACCEPT) encountered */ + BOOL check_lookbehind; /* Lookbehinds need later checking */ + int nltype; /* Newline type */ + int nllen; /* Newline string length */ + pcre_uchar nl[4]; /* Newline string when fixed length */ +} compile_data; + +/* Structure for maintaining a chain of pointers to the currently incomplete +branches, for testing for left recursion while compiling. */ + +typedef struct branch_chain { + struct branch_chain *outer; + pcre_uchar *current_branch; +} branch_chain; + +/* Structure for items in a linked list that represents an explicit recursive +call within the pattern; used by pcre_exec(). */ + +typedef struct recursion_info { + struct recursion_info *prevrec; /* Previous recursion record (or NULL) */ + int group_num; /* Number of group that was called */ + int *offset_save; /* Pointer to start of saved offsets */ + int saved_max; /* Number of saved offsets */ + PCRE_PUCHAR subject_position; /* Position at start of recursion */ +} recursion_info; + +/* A similar structure for pcre_dfa_exec(). */ + +typedef struct dfa_recursion_info { + struct dfa_recursion_info *prevrec; + int group_num; + PCRE_PUCHAR subject_position; +} dfa_recursion_info; + +/* Structure for building a chain of data for holding the values of the subject +pointer at the start of each subpattern, so as to detect when an empty string +has been matched by a subpattern - to break infinite loops; used by +pcre_exec(). */ + +typedef struct eptrblock { + struct eptrblock *epb_prev; + PCRE_PUCHAR epb_saved_eptr; +} eptrblock; + + +/* Structure for passing "static" information around between the functions +doing traditional NFA matching, so that they are thread-safe. */ + +typedef struct match_data { + unsigned long int match_call_count; /* As it says */ + unsigned long int match_limit; /* As it says */ + unsigned long int match_limit_recursion; /* As it says */ + int *offset_vector; /* Offset vector */ + int offset_end; /* One past the end */ + int offset_max; /* The maximum usable for return data */ + int nltype; /* Newline type */ + int nllen; /* Newline string length */ + int name_count; /* Number of names in name table */ + int name_entry_size; /* Size of entry in names table */ + pcre_uchar *name_table; /* Table of names */ + pcre_uchar nl[4]; /* Newline string when fixed */ + const pcre_uint8 *lcc; /* Points to lower casing table */ + const pcre_uint8 *fcc; /* Points to case-flipping table */ + const pcre_uint8 *ctypes; /* Points to table of type maps */ + BOOL offset_overflow; /* Set if too many extractions */ + BOOL notbol; /* NOTBOL flag */ + BOOL noteol; /* NOTEOL flag */ + BOOL utf; /* UTF-8 / UTF-16 flag */ + BOOL jscript_compat; /* JAVASCRIPT_COMPAT flag */ + BOOL use_ucp; /* PCRE_UCP flag */ + BOOL endonly; /* Dollar not before final \n */ + BOOL notempty; /* Empty string match not wanted */ + BOOL notempty_atstart; /* Empty string match at start not wanted */ + BOOL hitend; /* Hit the end of the subject at some point */ + BOOL bsr_anycrlf; /* \R is just any CRLF, not full Unicode */ + BOOL hasthen; /* Pattern contains (*THEN) */ + BOOL ignore_skip_arg; /* For re-run when SKIP name not found */ + const pcre_uchar *start_code; /* For use when recursing */ + PCRE_PUCHAR start_subject; /* Start of the subject string */ + PCRE_PUCHAR end_subject; /* End of the subject string */ + PCRE_PUCHAR start_match_ptr; /* Start of matched string */ + PCRE_PUCHAR end_match_ptr; /* Subject position at end match */ + PCRE_PUCHAR start_used_ptr; /* Earliest consulted character */ + int partial; /* PARTIAL options */ + int end_offset_top; /* Highwater mark at end of match */ + int capture_last; /* Most recent capture number */ + int start_offset; /* The start offset value */ + int match_function_type; /* Set for certain special calls of MATCH() */ + eptrblock *eptrchain; /* Chain of eptrblocks for tail recursions */ + int eptrn; /* Next free eptrblock */ + recursion_info *recursive; /* Linked list of recursion data */ + void *callout_data; /* To pass back to callouts */ + const pcre_uchar *mark; /* Mark pointer to pass back on success */ + const pcre_uchar *nomatch_mark;/* Mark pointer to pass back on failure */ + const pcre_uchar *once_target; /* Where to back up to for atomic groups */ +} match_data; + +/* A similar structure is used for the same purpose by the DFA matching +functions. */ + +typedef struct dfa_match_data { + const pcre_uchar *start_code; /* Start of the compiled pattern */ + const pcre_uchar *start_subject ; /* Start of the subject string */ + const pcre_uchar *end_subject; /* End of subject string */ + const pcre_uchar *start_used_ptr; /* Earliest consulted character */ + const pcre_uint8 *tables; /* Character tables */ + int start_offset; /* The start offset value */ + int moptions; /* Match options */ + int poptions; /* Pattern options */ + int nltype; /* Newline type */ + int nllen; /* Newline string length */ + pcre_uchar nl[4]; /* Newline string when fixed */ + void *callout_data; /* To pass back to callouts */ + dfa_recursion_info *recursive; /* Linked list of recursion data */ +} dfa_match_data; + +/* Bit definitions for entries in the pcre_ctypes table. */ + +#define ctype_space 0x01 +#define ctype_letter 0x02 +#define ctype_digit 0x04 +#define ctype_xdigit 0x08 +#define ctype_word 0x10 /* alphanumeric or '_' */ +#define ctype_meta 0x80 /* regexp meta char or zero (end pattern) */ + +/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set +of bits for a class map. Some classes are built by combining these tables. */ + +#define cbit_space 0 /* [:space:] or \s */ +#define cbit_xdigit 32 /* [:xdigit:] */ +#define cbit_digit 64 /* [:digit:] or \d */ +#define cbit_upper 96 /* [:upper:] */ +#define cbit_lower 128 /* [:lower:] */ +#define cbit_word 160 /* [:word:] or \w */ +#define cbit_graph 192 /* [:graph:] */ +#define cbit_print 224 /* [:print:] */ +#define cbit_punct 256 /* [:punct:] */ +#define cbit_cntrl 288 /* [:cntrl:] */ +#define cbit_length 320 /* Length of the cbits table */ + +/* Offsets of the various tables from the base tables pointer, and +total length. */ + +#define lcc_offset 0 +#define fcc_offset 256 +#define cbits_offset 512 +#define ctypes_offset (cbits_offset + cbit_length) +#define tables_length (ctypes_offset + 256) + +/* Internal function prefix */ + +#ifdef COMPILE_PCRE8 +#ifndef PUBL +#define PUBL(name) pcre_##name +#endif +#ifndef PRIV +#define PRIV(name) _pcre_##name +#endif +#else /* COMPILE_PCRE8 */ +#ifdef COMPILE_PCRE16 +#ifndef PUBL +#define PUBL(name) pcre16_##name +#endif +#ifndef PRIV +#define PRIV(name) _pcre16_##name +#endif +#else +#error Unsupported compiling mode +#endif /* COMPILE_PCRE16 */ +#endif /* COMPILE_PCRE8 */ + +/* Layout of the UCP type table that translates property names into types and +codes. Each entry used to point directly to a name, but to reduce the number of +relocations in shared libraries, it now has an offset into a single string +instead. */ + +typedef struct { + pcre_uint16 name_offset; + pcre_uint16 type; + pcre_uint16 value; +} ucp_type_table; + + +/* Internal shared data tables. These are tables that are used by more than one +of the exported public functions. They have to be "external" in the C sense, +but are not part of the PCRE public API. The data for these tables is in the +pcre_tables.c module. */ + +#ifdef COMPILE_PCRE8 + +extern const int PRIV(utf8_table1)[]; +extern const int PRIV(utf8_table1_size); +extern const int PRIV(utf8_table2)[]; +extern const int PRIV(utf8_table3)[]; +extern const pcre_uint8 PRIV(utf8_table4)[]; + +#endif /* COMPILE_PCRE8 */ + +extern const char PRIV(utt_names)[]; +extern const ucp_type_table PRIV(utt)[]; +extern const int PRIV(utt_size); + +extern const pcre_uint8 PRIV(default_tables)[]; + +extern const pcre_uint8 PRIV(OP_lengths)[]; + + +/* Internal shared functions. These are functions that are used by more than +one of the exported public functions. They have to be "external" in the C +sense, but are not part of the PCRE public API. */ + +/* String comparison functions. */ +#ifdef COMPILE_PCRE8 + +#define STRCMP_UC_UC(str1, str2) \ + strcmp((char *)(str1), (char *)(str2)) +#define STRCMP_UC_C8(str1, str2) \ + strcmp((char *)(str1), (str2)) +#define STRNCMP_UC_UC(str1, str2, num) \ + strncmp((char *)(str1), (char *)(str2), (num)) +#define STRNCMP_UC_C8(str1, str2, num) \ + strncmp((char *)(str1), (str2), (num)) +#define STRLEN_UC(str) strlen((const char *)str) + +#else + +extern int PRIV(strcmp_uc_uc)(const pcre_uchar *, + const pcre_uchar *); +extern int PRIV(strcmp_uc_c8)(const pcre_uchar *, + const char *); +extern int PRIV(strncmp_uc_uc)(const pcre_uchar *, + const pcre_uchar *, unsigned int num); +extern int PRIV(strncmp_uc_c8)(const pcre_uchar *, + const char *, unsigned int num); +extern unsigned int PRIV(strlen_uc)(const pcre_uchar *str); + +#define STRCMP_UC_UC(str1, str2) \ + PRIV(strcmp_uc_uc)((str1), (str2)) +#define STRCMP_UC_C8(str1, str2) \ + PRIV(strcmp_uc_c8)((str1), (str2)) +#define STRNCMP_UC_UC(str1, str2, num) \ + PRIV(strncmp_uc_uc)((str1), (str2), (num)) +#define STRNCMP_UC_C8(str1, str2, num) \ + PRIV(strncmp_uc_c8)((str1), (str2), (num)) +#define STRLEN_UC(str) PRIV(strlen_uc)(str) + +#endif /* COMPILE_PCRE8 */ + +extern const pcre_uchar *PRIV(find_bracket)(const pcre_uchar *, BOOL, int); +extern BOOL PRIV(is_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, + int *, BOOL); +extern int PRIV(ord2utf)(pcre_uint32, pcre_uchar *); +extern int PRIV(valid_utf)(PCRE_PUCHAR, int, int *); +extern BOOL PRIV(was_newline)(PCRE_PUCHAR, int, PCRE_PUCHAR, + int *, BOOL); +extern BOOL PRIV(xclass)(int, const pcre_uchar *, BOOL); + +#ifdef SUPPORT_JIT +extern void PRIV(jit_compile)(const REAL_PCRE *, PUBL(extra) *); +extern int PRIV(jit_exec)(const REAL_PCRE *, void *, + const pcre_uchar *, int, int, int, int, int *, int); +extern void PRIV(jit_free)(void *); +extern int PRIV(jit_get_size)(void *); +extern const char* PRIV(jit_get_target)(void); +#endif + +/* Unicode character database (UCD) */ + +typedef struct { + pcre_uint8 script; + pcre_uint8 chartype; + pcre_int32 other_case; +} ucd_record; + +extern const ucd_record PRIV(ucd_records)[]; +extern const pcre_uint8 PRIV(ucd_stage1)[]; +extern const pcre_uint16 PRIV(ucd_stage2)[]; +extern const int PRIV(ucp_gentype)[]; +#ifdef SUPPORT_JIT +extern const int PRIV(ucp_typerange)[]; +#endif + +#ifdef SUPPORT_UCP +/* UCD access macros */ + +#define UCD_BLOCK_SIZE 128 +#define GET_UCD(ch) (PRIV(ucd_records) + \ + PRIV(ucd_stage2)[PRIV(ucd_stage1)[(ch) / UCD_BLOCK_SIZE] * \ + UCD_BLOCK_SIZE + (ch) % UCD_BLOCK_SIZE]) + +#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype +#define UCD_SCRIPT(ch) GET_UCD(ch)->script +#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)] +#define UCD_OTHERCASE(ch) (ch + GET_UCD(ch)->other_case) + +#endif /* SUPPORT_UCP */ + +#endif + +/* End of pcre_internal.h */ diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c new file mode 100644 index 0000000000..f3d240d100 --- /dev/null +++ b/src/3rdparty/pcre/pcre_jit_compile.c @@ -0,0 +1,6915 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + + The machine code generator part (this module) was written by Zoltan Herczeg + Copyright (c) 2010-2012 + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#ifdef SUPPORT_JIT + +/* All-in-one: Since we use the JIT compiler only from here, +we just include it. This way we don't need to touch the build +system files. */ + +#define SLJIT_MALLOC(size) (PUBL(malloc))(size) +#define SLJIT_FREE(ptr) (PUBL(free))(ptr) +#define SLJIT_CONFIG_AUTO 1 +#define SLJIT_CONFIG_STATIC 1 +#define SLJIT_VERBOSE 0 +#define SLJIT_DEBUG 0 + +#include "sljit/sljitLir.c" + +#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED +#error Unsupported architecture +#endif + +/* Allocate memory on the stack. Fast, but limited size. */ +#define LOCAL_SPACE_SIZE 32768 + +#define STACK_GROWTH_RATE 8192 + +/* Enable to check that the allocation could destroy temporaries. */ +#if defined SLJIT_DEBUG && SLJIT_DEBUG +#define DESTROY_REGISTERS 1 +#endif + +/* +Short summary about the backtracking mechanism empolyed by the jit code generator: + +The code generator follows the recursive nature of the PERL compatible regular +expressions. The basic blocks of regular expressions are condition checkers +whose execute different commands depending on the result of the condition check. +The relationship between the operators can be horizontal (concatenation) and +vertical (sub-expression) (See struct fallback_common for more details). + + 'ab' - 'a' and 'b' regexps are concatenated + 'a+' - 'a' is the sub-expression of the '+' operator + +The condition checkers are boolean (true/false) checkers. Machine code is generated +for the checker itself and for the actions depending on the result of the checker. +The 'true' case is called as the hot path (expected path), and the other is called as +the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken +branches on the hot path. + + Greedy star operator (*) : + Hot path: match happens. + Fallback path: match failed. + Non-greedy star operator (*?) : + Hot path: no need to perform a match. + Fallback path: match is required. + +The following example shows how the code generated for a capturing bracket +with two alternatives. Let A, B, C, D are arbirary regular expressions, and +we have the following regular expression: + + A(B|C)D + +The generated code will be the following: + + A hot path + '(' hot path (pushing arguments to the stack) + B hot path + ')' hot path (pushing arguments to the stack) + D hot path + return with successful match + + D fallback path + ')' fallback path (If we arrived from "C" jump to the fallback of "C") + B fallback path + C expected path + jump to D hot path + C fallback path + A fallback path + + Notice, that the order of fallback code paths are the opposite of the fast + code paths. In this way the topmost value on the stack is always belong + to the current fallback code path. The fallback code path must check + whether there is a next alternative. If so, it needs to jump back to + the hot path eventually. Otherwise it needs to clear out its own stack + frame and continue the execution on the fallback code paths. +*/ + +/* +Saved stack frames: + +Atomic blocks and asserts require reloading the values of local variables +when the fallback mechanism performed. Because of OP_RECURSE, the locals +are not necessarly known in compile time, thus we need a dynamic restore +mechanism. + +The stack frames are stored in a chain list, and have the following format: +([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ] + +Thus we can restore the locals to a particular point in the stack. +*/ + +typedef struct jit_arguments { + /* Pointers first. */ + struct sljit_stack *stack; + const pcre_uchar *str; + const pcre_uchar *begin; + const pcre_uchar *end; + int *offsets; + pcre_uchar *ptr; + /* Everything else after. */ + int offsetcount; + int calllimit; + pcre_uint8 notbol; + pcre_uint8 noteol; + pcre_uint8 notempty; + pcre_uint8 notempty_atstart; +} jit_arguments; + +typedef struct executable_function { + void *executable_func; + PUBL(jit_callback) callback; + void *userdata; + sljit_uw executable_size; +} executable_function; + +typedef struct jump_list { + struct sljit_jump *jump; + struct jump_list *next; +} jump_list; + +enum stub_types { stack_alloc }; + +typedef struct stub_list { + enum stub_types type; + int data; + struct sljit_jump *start; + struct sljit_label *leave; + struct stub_list *next; +} stub_list; + +typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); + +/* The following structure is the key data type for the recursive +code generator. It is allocated by compile_hotpath, and contains +the aguments for compile_fallbackpath. Must be the first member +of its descendants. */ +typedef struct fallback_common { + /* Concatenation stack. */ + struct fallback_common *prev; + jump_list *nextfallbacks; + /* Internal stack (for component operators). */ + struct fallback_common *top; + jump_list *topfallbacks; + /* Opcode pointer. */ + pcre_uchar *cc; +} fallback_common; + +typedef struct assert_fallback { + fallback_common common; + jump_list *condfailed; + /* Less than 0 (-1) if a frame is not needed. */ + int framesize; + /* Points to our private memory word on the stack. */ + int localptr; + /* For iterators. */ + struct sljit_label *hotpath; +} assert_fallback; + +typedef struct bracket_fallback { + fallback_common common; + /* Where to coninue if an alternative is successfully matched. */ + struct sljit_label *althotpath; + /* For rmin and rmax iterators. */ + struct sljit_label *recursivehotpath; + /* For greedy ? operator. */ + struct sljit_label *zerohotpath; + /* Contains the branches of a failed condition. */ + union { + /* Both for OP_COND, OP_SCOND. */ + jump_list *condfailed; + assert_fallback *assert; + /* For OP_ONCE. -1 if not needed. */ + int framesize; + } u; + /* Points to our private memory word on the stack. */ + int localptr; +} bracket_fallback; + +typedef struct bracketpos_fallback { + fallback_common common; + /* Points to our private memory word on the stack. */ + int localptr; + /* Reverting stack is needed. */ + int framesize; + /* Allocated stack size. */ + int stacksize; +} bracketpos_fallback; + +typedef struct braminzero_fallback { + fallback_common common; + struct sljit_label *hotpath; +} braminzero_fallback; + +typedef struct iterator_fallback { + fallback_common common; + /* Next iteration. */ + struct sljit_label *hotpath; +} iterator_fallback; + +typedef struct recurse_entry { + struct recurse_entry *next; + /* Contains the function entry. */ + struct sljit_label *entry; + /* Collects the calls until the function is not created. */ + jump_list *calls; + /* Points to the starting opcode. */ + int start; +} recurse_entry; + +typedef struct recurse_fallback { + fallback_common common; +} recurse_fallback; + +typedef struct compiler_common { + struct sljit_compiler *compiler; + pcre_uchar *start; + int localsize; + int *localptrs; + const pcre_uint8 *fcc; + sljit_w lcc; + int cbraptr; + int nltype; + int newline; + int bsr_nltype; + int endonly; + sljit_w ctypes; + sljit_uw name_table; + sljit_w name_count; + sljit_w name_entry_size; + struct sljit_label *acceptlabel; + stub_list *stubs; + recurse_entry *entries; + recurse_entry *currententry; + jump_list *accept; + jump_list *calllimit; + jump_list *stackalloc; + jump_list *revertframes; + jump_list *wordboundary; + jump_list *anynewline; + jump_list *hspace; + jump_list *vspace; + jump_list *casefulcmp; + jump_list *caselesscmp; + BOOL jscript_compat; +#ifdef SUPPORT_UTF + BOOL utf; +#ifdef SUPPORT_UCP + BOOL use_ucp; +#endif + jump_list *utfreadchar; +#ifdef COMPILE_PCRE8 + jump_list *utfreadtype8; +#endif +#endif /* SUPPORT_UTF */ +#ifdef SUPPORT_UCP + jump_list *getucd; +#endif +} compiler_common; + +/* For byte_sequence_compare. */ + +typedef struct compare_context { + int length; + int sourcereg; +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + int ucharptr; + union { + sljit_i asint; + sljit_uh asushort; +#ifdef COMPILE_PCRE8 + sljit_ub asbyte; + sljit_ub asuchars[4]; +#else +#ifdef COMPILE_PCRE16 + sljit_uh asuchars[2]; +#endif +#endif + } c; + union { + sljit_i asint; + sljit_uh asushort; +#ifdef COMPILE_PCRE8 + sljit_ub asbyte; + sljit_ub asuchars[4]; +#else +#ifdef COMPILE_PCRE16 + sljit_uh asuchars[2]; +#endif +#endif + } oc; +#endif +} compare_context; + +enum { + frame_end = 0, + frame_setstrbegin = -1 +}; + +/* Undefine sljit macros. */ +#undef CMP + +/* Used for accessing the elements of the stack. */ +#define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) + +#define TMP1 SLJIT_TEMPORARY_REG1 +#define TMP2 SLJIT_TEMPORARY_REG3 +#define TMP3 SLJIT_TEMPORARY_EREG2 +#define STR_PTR SLJIT_SAVED_REG1 +#define STR_END SLJIT_SAVED_REG2 +#define STACK_TOP SLJIT_TEMPORARY_REG2 +#define STACK_LIMIT SLJIT_SAVED_REG3 +#define ARGUMENTS SLJIT_SAVED_EREG1 +#define CALL_COUNT SLJIT_SAVED_EREG2 +#define RETURN_ADDR SLJIT_TEMPORARY_EREG1 + +/* Locals layout. */ +/* These two locals can be used by the current opcode. */ +#define LOCALS0 (0 * sizeof(sljit_w)) +#define LOCALS1 (1 * sizeof(sljit_w)) +/* Two local variables for possessive quantifiers (char1 cannot use them). */ +#define POSSESSIVE0 (2 * sizeof(sljit_w)) +#define POSSESSIVE1 (3 * sizeof(sljit_w)) +/* Head of the last recursion. */ +#define RECURSIVE_HEAD (4 * sizeof(sljit_w)) +/* Max limit of recursions. */ +#define CALL_LIMIT (5 * sizeof(sljit_w)) +/* Last known position of the requested byte. */ +#define REQ_CHAR_PTR (6 * sizeof(sljit_w)) +/* End pointer of the first line. */ +#define FIRSTLINE_END (7 * sizeof(sljit_w)) +/* The output vector is stored on the stack, and contains pointers +to characters. The vector data is divided into two groups: the first +group contains the start / end character pointers, and the second is +the start pointers when the end of the capturing group has not yet reached. */ +#define OVECTOR_START (8 * sizeof(sljit_w)) +#define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) +#define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) +#define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) + +#ifdef COMPILE_PCRE8 +#define MOV_UCHAR SLJIT_MOV_UB +#define MOVU_UCHAR SLJIT_MOVU_UB +#else +#ifdef COMPILE_PCRE16 +#define MOV_UCHAR SLJIT_MOV_UH +#define MOVU_UCHAR SLJIT_MOVU_UH +#else +#error Unsupported compiling mode +#endif +#endif + +/* Shortcuts. */ +#define DEFINE_COMPILER \ + struct sljit_compiler *compiler = common->compiler +#define OP1(op, dst, dstw, src, srcw) \ + sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw)) +#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \ + sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w)) +#define LABEL() \ + sljit_emit_label(compiler) +#define JUMP(type) \ + sljit_emit_jump(compiler, (type)) +#define JUMPTO(type, label) \ + sljit_set_label(sljit_emit_jump(compiler, (type)), (label)) +#define JUMPHERE(jump) \ + sljit_set_label((jump), sljit_emit_label(compiler)) +#define CMP(type, src1, src1w, src2, src2w) \ + sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) +#define CMPTO(type, src1, src1w, src2, src2w, label) \ + sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) +#define COND_VALUE(op, dst, dstw, type) \ + sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) + +static pcre_uchar* bracketend(pcre_uchar* cc) +{ +SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); +do cc += GET(cc, 1); while (*cc == OP_ALT); +SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); +cc += 1 + LINK_SIZE; +return cc; +} + +/* Functions whose might need modification for all new supported opcodes: + next_opcode + get_localspace + set_localptrs + get_framesize + init_frame + get_localsize + copy_locals + compile_hotpath + compile_fallbackpath +*/ + +static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) +{ +SLJIT_UNUSED_ARG(common); +switch(*cc) + { + case OP_SOD: + case OP_SOM: + case OP_SET_SOM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + case OP_ANYNL: + case OP_NOT_HSPACE: + case OP_HSPACE: + case OP_NOT_VSPACE: + case OP_VSPACE: + case OP_EXTUNI: + case OP_EODN: + case OP_EOD: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_DEF: + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + case OP_FAIL: + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + case OP_SKIPZERO: + return cc + 1; + + case OP_ANYBYTE: +#ifdef SUPPORT_UTF + if (common->utf) return NULL; +#endif + return cc + 1; + + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_POSSTAR: + case OP_POSPLUS: + case OP_POSQUERY: + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_POSSTARI: + case OP_POSPLUSI: + case OP_POSQUERYI: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + case OP_NOTPOSQUERY: + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERYI: + cc += 2; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + return cc; + + case OP_UPTO: + case OP_MINUPTO: + case OP_EXACT: + case OP_POSUPTO: + case OP_UPTOI: + case OP_MINUPTOI: + case OP_EXACTI: + case OP_POSUPTOI: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTEXACT: + case OP_NOTPOSUPTO: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTEXACTI: + case OP_NOTPOSUPTOI: + cc += 2 + IMM2_SIZE; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + return cc; + + case OP_NOTPROP: + case OP_PROP: + return cc + 1 + 2; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + case OP_TYPEPOSUPTO: + case OP_REF: + case OP_REFI: + case OP_CREF: + case OP_NCREF: + case OP_RREF: + case OP_NRREF: + case OP_CLOSE: + cc += 1 + IMM2_SIZE; + return cc; + + case OP_CRRANGE: + case OP_CRMINRANGE: + return cc + 1 + 2 * IMM2_SIZE; + + case OP_CLASS: + case OP_NCLASS: + return cc + 1 + 32 / sizeof(pcre_uchar); + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: + return cc + GET(cc, 1); +#endif + + case OP_RECURSE: + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_REVERSE: + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRA: + case OP_BRAPOS: + case OP_COND: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_KETRPOS: + return cc + 1 + LINK_SIZE; + + case OP_CBRA: + case OP_CBRAPOS: + case OP_SCBRA: + case OP_SCBRAPOS: + return cc + 1 + LINK_SIZE + IMM2_SIZE; + + default: + return NULL; + } +} + +static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) +{ +int localspace = 0; +pcre_uchar *alternative; +/* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ +while (cc < ccend) + { + switch(*cc) + { + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRAPOS: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + localspace += sizeof(sljit_w); + cc += 1 + LINK_SIZE; + break; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + localspace += sizeof(sljit_w); + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_COND: + /* Might be a hidden SCOND. */ + alternative = cc + GET(cc, 1); + if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + localspace += sizeof(sljit_w); + cc += 1 + LINK_SIZE; + break; + + default: + cc = next_opcode(common, cc); + if (cc == NULL) + return -1; + break; + } + } +return localspace; +} + +static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend) +{ +pcre_uchar *cc = common->start; +pcre_uchar *alternative; +while (cc < ccend) + { + switch(*cc) + { + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRAPOS: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + common->localptrs[cc - common->start] = localptr; + localptr += sizeof(sljit_w); + cc += 1 + LINK_SIZE; + break; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + common->localptrs[cc - common->start] = localptr; + localptr += sizeof(sljit_w); + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_COND: + /* Might be a hidden SCOND. */ + alternative = cc + GET(cc, 1); + if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + { + common->localptrs[cc - common->start] = localptr; + localptr += sizeof(sljit_w); + } + cc += 1 + LINK_SIZE; + break; + + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); + break; + } + } +} + +/* Returns with -1 if no need for frame. */ +static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive) +{ +pcre_uchar *ccend = bracketend(cc); +int length = 0; +BOOL possessive = FALSE; +BOOL setsom_found = FALSE; + +if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) + { + length = 3; + possessive = TRUE; + } + +cc = next_opcode(common, cc); +SLJIT_ASSERT(cc != NULL); +while (cc < ccend) + switch(*cc) + { + case OP_SET_SOM: + case OP_RECURSE: + if (!setsom_found) + { + length += 2; + setsom_found = TRUE; + } + cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; + break; + + case OP_CBRA: + case OP_CBRAPOS: + case OP_SCBRA: + case OP_SCBRAPOS: + length += 3; + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); + break; + } + +/* Possessive quantifiers can use a special case. */ +if (SLJIT_UNLIKELY(possessive) && length == 3) + return -1; + +if (length > 0) + return length + 1; +return -1; +} + +static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive) +{ +DEFINE_COMPILER; +pcre_uchar *ccend = bracketend(cc); +BOOL setsom_found = FALSE; +int offset; + +/* >= 1 + shortest item size (2) */ +SLJIT_UNUSED_ARG(stacktop); +SLJIT_ASSERT(stackpos >= stacktop + 2); + +stackpos = STACK(stackpos); +if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) + cc = next_opcode(common, cc); +SLJIT_ASSERT(cc != NULL); +while (cc < ccend) + switch(*cc) + { + case OP_SET_SOM: + case OP_RECURSE: + if (!setsom_found) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); + stackpos += (int)sizeof(sljit_w); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); + stackpos += (int)sizeof(sljit_w); + setsom_found = TRUE; + } + cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; + break; + + case OP_CBRA: + case OP_CBRAPOS: + case OP_SCBRA: + case OP_SCBRAPOS: + offset = (GET2(cc, 1 + LINK_SIZE)) << 1; + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); + stackpos += (int)sizeof(sljit_w); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); + stackpos += (int)sizeof(sljit_w); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); + stackpos += (int)sizeof(sljit_w); + + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); + break; + } + +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end); +SLJIT_ASSERT(stackpos == STACK(stacktop)); +} + +static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) +{ +int localsize = 2; +pcre_uchar *alternative; +/* Calculate the sum of the local variables. */ +while (cc < ccend) + { + switch(*cc) + { + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRAPOS: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + localsize++; + cc += 1 + LINK_SIZE; + break; + + case OP_CBRA: + case OP_SCBRA: + localsize++; + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + localsize += 2; + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_COND: + /* Might be a hidden SCOND. */ + alternative = cc + GET(cc, 1); + if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + localsize++; + cc += 1 + LINK_SIZE; + break; + + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); + break; + } + } +SLJIT_ASSERT(cc == ccend); +return localsize; +} + +static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, + BOOL save, int stackptr, int stacktop) +{ +DEFINE_COMPILER; +int srcw[2]; +int count; +BOOL tmp1next = TRUE; +BOOL tmp1empty = TRUE; +BOOL tmp2empty = TRUE; +pcre_uchar *alternative; +enum { + start, + loop, + end +} status; + +status = save ? start : loop; +stackptr = STACK(stackptr - 2); +stacktop = STACK(stacktop - 1); + +if (!save) + { + stackptr += sizeof(sljit_w); + if (stackptr < stacktop) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); + stackptr += sizeof(sljit_w); + tmp1empty = FALSE; + } + if (stackptr < stacktop) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); + stackptr += sizeof(sljit_w); + tmp2empty = FALSE; + } + /* The tmp1next must be TRUE in either way. */ + } + +while (status != end) + { + count = 0; + switch(status) + { + case start: + SLJIT_ASSERT(save); + count = 1; + srcw[0] = RECURSIVE_HEAD; + status = loop; + break; + + case loop: + if (cc >= ccend) + { + status = end; + break; + } + + switch(*cc) + { + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRAPOS: + case OP_SBRA: + case OP_SBRAPOS: + case OP_SCOND: + count = 1; + srcw[0] = PRIV_DATA(cc); + SLJIT_ASSERT(srcw[0] != 0); + cc += 1 + LINK_SIZE; + break; + + case OP_CBRA: + case OP_SCBRA: + count = 1; + srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + count = 2; + srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); + srcw[0] = PRIV_DATA(cc); + SLJIT_ASSERT(srcw[0] != 0); + cc += 1 + LINK_SIZE + IMM2_SIZE; + break; + + case OP_COND: + /* Might be a hidden SCOND. */ + alternative = cc + GET(cc, 1); + if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) + { + count = 1; + srcw[0] = PRIV_DATA(cc); + SLJIT_ASSERT(srcw[0] != 0); + } + cc += 1 + LINK_SIZE; + break; + + default: + cc = next_opcode(common, cc); + SLJIT_ASSERT(cc != NULL); + break; + } + break; + + case end: + SLJIT_ASSERT_STOP(); + break; + } + + while (count > 0) + { + count--; + if (save) + { + if (tmp1next) + { + if (!tmp1empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); + stackptr += sizeof(sljit_w); + } + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); + tmp1empty = FALSE; + tmp1next = FALSE; + } + else + { + if (!tmp2empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); + stackptr += sizeof(sljit_w); + } + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]); + tmp2empty = FALSE; + tmp1next = TRUE; + } + } + else + { + if (tmp1next) + { + SLJIT_ASSERT(!tmp1empty); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0); + tmp1empty = stackptr >= stacktop; + if (!tmp1empty) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); + stackptr += sizeof(sljit_w); + } + tmp1next = FALSE; + } + else + { + SLJIT_ASSERT(!tmp2empty); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0); + tmp2empty = stackptr >= stacktop; + if (!tmp2empty) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr); + stackptr += sizeof(sljit_w); + } + tmp1next = TRUE; + } + } + } + } + +if (save) + { + if (tmp1next) + { + if (!tmp1empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); + stackptr += sizeof(sljit_w); + } + if (!tmp2empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); + stackptr += sizeof(sljit_w); + } + } + else + { + if (!tmp2empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0); + stackptr += sizeof(sljit_w); + } + if (!tmp1empty) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0); + stackptr += sizeof(sljit_w); + } + } + } +SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); +} + +static SLJIT_INLINE BOOL ispowerof2(unsigned int value) +{ +return (value & (value - 1)) == 0; +} + +static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label) +{ +while (list) + { + /* sljit_set_label is clever enough to do nothing + if either the jump or the label is NULL */ + sljit_set_label(list->jump, label); + list = list->next; + } +} + +static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump) +{ +jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list)); +if (list_item) + { + list_item->next = *list; + list_item->jump = jump; + *list = list_item; + } +} + +static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start) +{ +DEFINE_COMPILER; +stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); + +if (list_item) + { + list_item->type = type; + list_item->data = data; + list_item->start = start; + list_item->leave = LABEL(); + list_item->next = common->stubs; + common->stubs = list_item; + } +} + +static void flush_stubs(compiler_common *common) +{ +DEFINE_COMPILER; +stub_list* list_item = common->stubs; + +while (list_item) + { + JUMPHERE(list_item->start); + switch(list_item->type) + { + case stack_alloc: + add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); + break; + } + JUMPTO(SLJIT_JUMP, list_item->leave); + list_item = list_item->next; + } +common->stubs = NULL; +} + +static SLJIT_INLINE void decrease_call_count(compiler_common *common) +{ +DEFINE_COMPILER; + +OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1); +add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO)); +} + +static SLJIT_INLINE void allocate_stack(compiler_common *common, int size) +{ +/* May destroy all locals and registers except TMP2. */ +DEFINE_COMPILER; + +OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w)); +#ifdef DESTROY_REGISTERS +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345); +OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); +OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); +#endif +add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); +} + +static SLJIT_INLINE void free_stack(compiler_common *common, int size) +{ +DEFINE_COMPILER; +OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w)); +} + +static SLJIT_INLINE void reset_ovector(compiler_common *common, int length) +{ +DEFINE_COMPILER; +struct sljit_label *loop; +int i; +/* At this point we can freely use all temporary registers. */ +/* TMP1 returns with begin - 1. */ +OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); +if (length < 8) + { + for (i = 0; i < length; i++) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0); + } +else + { + OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); + loop = LABEL(); + OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_C_NOT_ZERO, loop); + } +} + +static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) +{ +DEFINE_COMPILER; +struct sljit_label *loop; +struct sljit_jump *earlyexit; + +/* At this point we can freely use all registers. */ +OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); + +OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); +OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); +OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); +OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); +/* Unlikely, but possible */ +earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); +loop = LABEL(); +OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); +OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); +/* Copy the integer value to the output buffer */ +#ifdef COMPILE_PCRE16 +OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); +#endif +OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); +JUMPTO(SLJIT_C_NOT_ZERO, loop); +JUMPHERE(earlyexit); + +/* Calculate the return value, which is the maximum ovector value. */ +if (topbracket > 1) + { + OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); + + /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ + loop = LABEL(); + OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); + OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); + CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); + } +else + OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); +} + +static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) +{ +/* Detects if the character has an othercase. */ +unsigned int c; + +#ifdef SUPPORT_UTF +if (common->utf) + { + GETCHAR(c, cc); + if (c > 127) + { +#ifdef SUPPORT_UCP + return c != UCD_OTHERCASE(c); +#else + return FALSE; +#endif + } +#ifndef COMPILE_PCRE8 + return common->fcc[c] != c; +#endif + } +else +#endif + c = *cc; +return MAX_255(c) ? common->fcc[c] != c : FALSE; +} + +static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c) +{ +/* Returns with the othercase. */ +#ifdef SUPPORT_UTF +if (common->utf && c > 127) + { +#ifdef SUPPORT_UCP + return UCD_OTHERCASE(c); +#else + return c; +#endif + } +#endif +return TABLE_GET(c, common->fcc, c); +} + +static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc) +{ +/* Detects if the character and its othercase has only 1 bit difference. */ +unsigned int c, oc, bit; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +int n; +#endif + +#ifdef SUPPORT_UTF +if (common->utf) + { + GETCHAR(c, cc); + if (c <= 127) + oc = common->fcc[c]; + else + { +#ifdef SUPPORT_UCP + oc = UCD_OTHERCASE(c); +#else + oc = c; +#endif + } + } +else + { + c = *cc; + oc = TABLE_GET(c, common->fcc, c); + } +#else +c = *cc; +oc = TABLE_GET(c, common->fcc, c); +#endif + +SLJIT_ASSERT(c != oc); + +bit = c ^ oc; +/* Optimized for English alphabet. */ +if (c <= 127 && bit == 0x20) + return (0 << 8) | 0x20; + +/* Since c != oc, they must have at least 1 bit difference. */ +if (!ispowerof2(bit)) + return 0; + +#ifdef COMPILE_PCRE8 + +#ifdef SUPPORT_UTF +if (common->utf && c > 127) + { + n = GET_EXTRALEN(*cc); + while ((bit & 0x3f) == 0) + { + n--; + bit >>= 6; + } + return (n << 8) | bit; + } +#endif /* SUPPORT_UTF */ +return (0 << 8) | bit; + +#else /* COMPILE_PCRE8 */ + +#ifdef COMPILE_PCRE16 +#ifdef SUPPORT_UTF +if (common->utf && c > 65535) + { + if (bit >= (1 << 10)) + bit >>= 10; + else + return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8)); + } +#endif /* SUPPORT_UTF */ +return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8)); +#endif /* COMPILE_PCRE16 */ + +#endif /* COMPILE_PCRE8 */ +} + +static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks) +{ +DEFINE_COMPILER; +add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); +} + +static void read_char(compiler_common *common) +{ +/* Reads the character into TMP1, updates STR_PTR. +Does not check STR_END. TMP2 Destroyed. */ +DEFINE_COMPILER; +#ifdef SUPPORT_UTF +struct sljit_jump *jump; +#endif + +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); +#ifdef SUPPORT_UTF +if (common->utf) + { +#ifdef COMPILE_PCRE8 + jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); +#else +#ifdef COMPILE_PCRE16 + jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); +#endif +#endif /* COMPILE_PCRE8 */ + add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); + JUMPHERE(jump); + } +#endif +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +} + +static void peek_char(compiler_common *common) +{ +/* Reads the character into TMP1, keeps STR_PTR. +Does not check STR_END. TMP2 Destroyed. */ +DEFINE_COMPILER; +#ifdef SUPPORT_UTF +struct sljit_jump *jump; +#endif + +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); +#ifdef SUPPORT_UTF +if (common->utf) + { +#ifdef COMPILE_PCRE8 + jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); +#else +#ifdef COMPILE_PCRE16 + jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); +#endif +#endif /* COMPILE_PCRE8 */ + add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + JUMPHERE(jump); + } +#endif +} + +static void read_char8_type(compiler_common *common) +{ +/* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ +DEFINE_COMPILER; +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 +struct sljit_jump *jump; +#endif + +#ifdef SUPPORT_UTF +if (common->utf) + { + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#ifdef COMPILE_PCRE8 + /* This can be an extra read in some situations, but hopefully + it is needed in most cases. */ + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); + jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); + add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); + JUMPHERE(jump); +#else +#ifdef COMPILE_PCRE16 + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); + JUMPHERE(jump); + /* Skip low surrogate if necessary. */ + OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +#endif +#endif /* COMPILE_PCRE8 */ + return; + } +#endif +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#ifdef COMPILE_PCRE16 +/* The ctypes array contains only 256 values. */ +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); +jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); +#endif +OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +#ifdef COMPILE_PCRE16 +JUMPHERE(jump); +#endif +} + +static void skip_char_back(compiler_common *common) +{ +/* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */ +DEFINE_COMPILER; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +struct sljit_label *label; + +if (common->utf) + { + label = LABEL(); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); + CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); + return; + } +#endif +#if defined SUPPORT_UTF && defined COMPILE_PCRE16 +if (common->utf) + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + /* Skip low surrogate if necessary. */ + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + return; + } +#endif +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +} + +static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue) +{ +/* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */ +DEFINE_COMPILER; + +if (nltype == NLTYPE_ANY) + { + add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + } +else if (nltype == NLTYPE_ANYCRLF) + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + } +else + { + SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); + add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); + } +} + +#ifdef SUPPORT_UTF + +#ifdef COMPILE_PCRE8 +static void do_utfreadchar(compiler_common *common) +{ +/* Fast decoding a UTF-8 character. TMP1 contains the first byte +of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */ +DEFINE_COMPILER; +struct sljit_jump *jump; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +/* Searching for the first zero. */ +OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); +jump = JUMP(SLJIT_C_NOT_ZERO); +/* Two byte sequence. */ +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f); +OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +JUMPHERE(jump); + +OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10); +jump = JUMP(SLJIT_C_NOT_ZERO); +/* Three byte sequence. */ +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f); +OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +JUMPHERE(jump); + +/* Four byte sequence. */ +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07); +OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3)); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +static void do_utfreadtype8(compiler_common *common) +{ +/* Fast decoding a UTF-8 character type. TMP2 contains the first byte +of the character (>= 0xc0). Return value in TMP1. */ +DEFINE_COMPILER; +struct sljit_jump *jump; +struct sljit_jump *compare; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); + +OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); +jump = JUMP(SLJIT_C_NOT_ZERO); +/* Two byte sequence. */ +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); +OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); +OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); +compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); +OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); + +JUMPHERE(compare); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +JUMPHERE(jump); + +/* We only have types for characters less than 256. */ +OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +#else /* COMPILE_PCRE8 */ + +#ifdef COMPILE_PCRE16 +static void do_utfreadchar(compiler_common *common) +{ +/* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char +of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */ +DEFINE_COMPILER; +struct sljit_jump *jump; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); +/* Do nothing, only return. */ +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); + +JUMPHERE(jump); +/* Combine two 16 bit characters. */ +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); +OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff); +OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} +#endif /* COMPILE_PCRE16 */ + +#endif /* COMPILE_PCRE8 */ + +#endif /* SUPPORT_UTF */ + +#ifdef SUPPORT_UCP + +/* UCD_BLOCK_SIZE must be 128 (see the assert below). */ +#define UCD_BLOCK_MASK 127 +#define UCD_BLOCK_SHIFT 7 + +static void do_getucd(compiler_common *common) +{ +/* Search the UCD record for the character comes in TMP1. +Returns chartype in TMP1 and UCD offset in TMP2. */ +DEFINE_COMPILER; + +SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8); + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); +OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1)); +OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); +OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_stage2)); +OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); +OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} +#endif + +static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline) +{ +DEFINE_COMPILER; +struct sljit_label *mainloop; +struct sljit_label *newlinelabel = NULL; +struct sljit_jump *start; +struct sljit_jump *end = NULL; +struct sljit_jump *nl = NULL; +#ifdef SUPPORT_UTF +struct sljit_jump *singlechar; +#endif +jump_list *newline = NULL; +BOOL newlinecheck = FALSE; +BOOL readuchar = FALSE; + +if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || + common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) + newlinecheck = TRUE; + +if (firstline) + { + /* Search for the end of the first line. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0); + + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + mainloop = LABEL(); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); + CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } + else + { + end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + mainloop = LABEL(); + /* Continual stores does not cause data dependency. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0); + read_char(common); + check_newlinechar(common, common->nltype, &newline, TRUE); + CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0); + set_jumps(newline, LABEL()); + } + + JUMPHERE(end); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + } + +start = JUMP(SLJIT_JUMP); + +if (newlinecheck) + { + newlinelabel = LABEL(); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); +#ifdef COMPILE_PCRE16 + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); +#endif + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + nl = JUMP(SLJIT_JUMP); + } + +mainloop = LABEL(); + +/* Increasing the STR_PTR here requires one less jump in the most common case. */ +#ifdef SUPPORT_UTF +if (common->utf) readuchar = TRUE; +#endif +if (newlinecheck) readuchar = TRUE; + +if (readuchar) + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + +if (newlinecheck) + CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +if (common->utf) + { + singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + JUMPHERE(singlechar); + } +#endif +#if defined SUPPORT_UTF && defined COMPILE_PCRE16 +if (common->utf) + { + singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + JUMPHERE(singlechar); + } +#endif +JUMPHERE(start); + +if (newlinecheck) + { + JUMPHERE(end); + JUMPHERE(nl); + } + +return mainloop; +} + +static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) +{ +DEFINE_COMPILER; +struct sljit_label *start; +struct sljit_jump *leave; +struct sljit_jump *found; +pcre_uchar oc, bit; + +if (firstline) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); + } + +start = LABEL(); +leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + +oc = first_char; +if (caseless) + { + oc = TABLE_GET(first_char, common->fcc, first_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (first_char > 127 && common->utf) + oc = UCD_OTHERCASE(first_char); +#endif + } +if (first_char == oc) + found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char); +else + { + bit = first_char ^ oc; + if (ispowerof2(bit)) + { + OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); + found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit); + } + else + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + found = JUMP(SLJIT_C_NOT_ZERO); + } + } + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +if (common->utf) + { + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + } +#endif +#if defined SUPPORT_UTF && defined COMPILE_PCRE16 +if (common->utf) + { + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + } +#endif +JUMPTO(SLJIT_JUMP, start); +JUMPHERE(found); +JUMPHERE(leave); + +if (firstline) + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); +} + +static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline) +{ +DEFINE_COMPILER; +struct sljit_label *loop; +struct sljit_jump *lastchar; +struct sljit_jump *firstchar; +struct sljit_jump *leave; +struct sljit_jump *foundcr = NULL; +struct sljit_jump *notfoundnl; +jump_list *newline = NULL; + +if (firstline) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); + } + +if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); + + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL); +#ifdef COMPILE_PCRE16 + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); +#endif + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + + loop = LABEL(); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); + CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); + + JUMPHERE(leave); + JUMPHERE(firstchar); + JUMPHERE(lastchar); + + if (firstline) + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + return; + } + +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); +firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); +skip_char_back(common); + +loop = LABEL(); +read_char(common); +lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) + foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); +check_newlinechar(common, common->nltype, &newline, FALSE); +set_jumps(newline, loop); + +if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) + { + leave = JUMP(SLJIT_JUMP); + JUMPHERE(foundcr); + notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); +#ifdef COMPILE_PCRE16 + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); +#endif + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + JUMPHERE(notfoundnl); + JUMPHERE(leave); + } +JUMPHERE(lastchar); +JUMPHERE(firstchar); + +if (firstline) + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); +} + +static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) +{ +DEFINE_COMPILER; +struct sljit_label *start; +struct sljit_jump *leave; +struct sljit_jump *found; +#ifndef COMPILE_PCRE8 +struct sljit_jump *jump; +#endif + +if (firstline) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0); + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); + } + +start = LABEL(); +leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); +#ifdef SUPPORT_UTF +if (common->utf) + OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); +#endif +#ifndef COMPILE_PCRE8 +jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); +JUMPHERE(jump); +#endif +OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); +OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); +OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits); +OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); +OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); +found = JUMP(SLJIT_C_NOT_ZERO); + +#ifdef SUPPORT_UTF +if (common->utf) + OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); +#endif +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +if (common->utf) + { + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + } +#endif +#if defined SUPPORT_UTF && defined COMPILE_PCRE16 +if (common->utf) + { + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + } +#endif +JUMPTO(SLJIT_JUMP, start); +JUMPHERE(found); +JUMPHERE(leave); + +if (firstline) + OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); +} + +static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) +{ +DEFINE_COMPILER; +struct sljit_label *loop; +struct sljit_jump *toolong; +struct sljit_jump *alreadyfound; +struct sljit_jump *found; +struct sljit_jump *foundoc = NULL; +struct sljit_jump *notfound; +pcre_uchar oc, bit; + +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR); +OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); +toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); +alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); + +if (has_firstchar) + OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +else + OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); + +loop = LABEL(); +notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); + +OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); +oc = req_char; +if (caseless) + { + oc = TABLE_GET(req_char, common->fcc, req_char); +#if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) + if (req_char > 127 && common->utf) + oc = UCD_OTHERCASE(req_char); +#endif + } +if (req_char == oc) + found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); +else + { + bit = req_char ^ oc; + if (ispowerof2(bit)) + { + OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); + found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); + } + else + { + found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); + foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); + } + } +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); +JUMPTO(SLJIT_JUMP, loop); + +JUMPHERE(found); +if (foundoc) + JUMPHERE(foundoc); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, TMP1, 0); +JUMPHERE(alreadyfound); +JUMPHERE(toolong); +return notfound; +} + +static void do_revertframes(compiler_common *common) +{ +DEFINE_COMPILER; +struct sljit_jump *jump; +struct sljit_label *mainloop; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); + +/* Drop frames until we reach STACK_TOP. */ +mainloop = LABEL(); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); +jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); +OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w)); +JUMPTO(SLJIT_JUMP, mainloop); + +JUMPHERE(jump); +jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); +/* End of dropping frames. */ +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); + +JUMPHERE(jump); +jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin); +/* Set string begin. */ +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); +JUMPTO(SLJIT_JUMP, mainloop); + +JUMPHERE(jump); +/* Unknown command. */ +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w)); +JUMPTO(SLJIT_JUMP, mainloop); +} + +static void check_wordboundary(compiler_common *common) +{ +DEFINE_COMPILER; +struct sljit_jump *beginend; +#if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF +struct sljit_jump *jump; +#endif + +SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); + +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize); +/* Get type of the previous char, and put it to LOCALS1. */ +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); +beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); +skip_char_back(common); +read_char(common); + +/* Testing char type. */ +#ifdef SUPPORT_UCP +if (common->use_ucp) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); + jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); + add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); + JUMPHERE(jump); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); + } +else +#endif + { +#ifndef COMPILE_PCRE8 + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#elif defined SUPPORT_UTF + /* Here LOCALS1 has already been zeroed. */ + jump = NULL; + if (common->utf) + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#endif /* COMPILE_PCRE8 */ + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); +#ifndef COMPILE_PCRE8 + JUMPHERE(jump); +#elif defined SUPPORT_UTF + if (jump != NULL) + JUMPHERE(jump); +#endif /* COMPILE_PCRE8 */ + } +JUMPHERE(beginend); + +OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); +beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); +peek_char(common); + +/* Testing char type. This is a code duplication. */ +#ifdef SUPPORT_UCP +if (common->use_ucp) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); + jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); + add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); + JUMPHERE(jump); + } +else +#endif + { +#ifndef COMPILE_PCRE8 + /* TMP2 may be destroyed by peek_char. */ + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#elif defined SUPPORT_UTF + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); + jump = NULL; + if (common->utf) + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#endif + OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); + OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); + OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); +#ifndef COMPILE_PCRE8 + JUMPHERE(jump); +#elif defined SUPPORT_UTF + if (jump != NULL) + JUMPHERE(jump); +#endif /* COMPILE_PCRE8 */ + } +JUMPHERE(beginend); + +OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); +sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +} + +static void check_anynewline(compiler_common *common) +{ +/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ +DEFINE_COMPILER; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); + +OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); +OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); +COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 +#ifdef COMPILE_PCRE8 +if (common->utf) + { +#endif + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); +#ifdef COMPILE_PCRE8 + } +#endif +#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ +COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +static void check_hspace(compiler_common *common) +{ +/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ +DEFINE_COMPILER; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); + +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); +COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); +COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 +#ifdef COMPILE_PCRE8 +if (common->utf) + { +#endif + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); +#ifdef COMPILE_PCRE8 + } +#endif +#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ +COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +static void check_vspace(compiler_common *common) +{ +/* Check whether TMP1 contains a newline character. TMP2 destroyed. */ +DEFINE_COMPILER; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); + +OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); +OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); +COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); +OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 +#ifdef COMPILE_PCRE8 +if (common->utf) + { +#endif + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); +#ifdef COMPILE_PCRE8 + } +#endif +#endif /* SUPPORT_UTF || COMPILE_PCRE16 */ +COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +#define CHAR1 STR_END +#define CHAR2 STACK_TOP + +static void do_casefulcmp(compiler_common *common) +{ +DEFINE_COMPILER; +struct sljit_jump *jump; +struct sljit_label *label; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); +OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + +label = LABEL(); +OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); +OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); +OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); +JUMPTO(SLJIT_C_NOT_ZERO, label); + +JUMPHERE(jump); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); +OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +#define LCC_TABLE STACK_LIMIT + +static void do_caselesscmp(compiler_common *common) +{ +DEFINE_COMPILER; +struct sljit_jump *jump; +struct sljit_label *label; + +sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + +OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0); +OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); +OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + +label = LABEL(); +OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); +OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); +#ifndef COMPILE_PCRE8 +jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255); +#endif +OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); +#ifndef COMPILE_PCRE8 +JUMPHERE(jump); +jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255); +#endif +OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); +#ifndef COMPILE_PCRE8 +JUMPHERE(jump); +#endif +jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); +OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); +JUMPTO(SLJIT_C_NOT_ZERO, label); + +JUMPHERE(jump); +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); +OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); +OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); +sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +} + +#undef LCC_TABLE +#undef CHAR1 +#undef CHAR2 + +#if defined SUPPORT_UTF && defined SUPPORT_UCP + +static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) +{ +/* This function would be ineffective to do in JIT level. */ +int c1, c2; +const pcre_uchar *src2 = args->ptr; +const pcre_uchar *end2 = args->end; + +while (src1 < end1) + { + if (src2 >= end2) + return 0; + GETCHARINC(c1, src1); + GETCHARINC(c2, src2); + if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0; + } +return src2; +} + +#endif /* SUPPORT_UTF && SUPPORT_UCP */ + +static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, + compare_context* context, jump_list **fallbacks) +{ +DEFINE_COMPILER; +unsigned int othercasebit = 0; +pcre_uchar *othercasechar = NULL; +#ifdef SUPPORT_UTF +int utflength; +#endif + +if (caseless && char_has_othercase(common, cc)) + { + othercasebit = char_get_othercase_bit(common, cc); + SLJIT_ASSERT(othercasebit); + /* Extracting bit difference info. */ +#ifdef COMPILE_PCRE8 + othercasechar = cc + (othercasebit >> 8); + othercasebit &= 0xff; +#else +#ifdef COMPILE_PCRE16 + othercasechar = cc + (othercasebit >> 9); + if ((othercasebit & 0x100) != 0) + othercasebit = (othercasebit & 0xff) << 8; + else + othercasebit &= 0xff; +#endif +#endif + } + +if (context->sourcereg == -1) + { +#ifdef COMPILE_PCRE8 +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + if (context->length >= 4) + OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else if (context->length >= 2) + OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else +#endif + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); +#else +#ifdef COMPILE_PCRE16 +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + if (context->length >= 4) + OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); + else +#endif + OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); +#endif +#endif /* COMPILE_PCRE8 */ + context->sourcereg = TMP2; + } + +#ifdef SUPPORT_UTF +utflength = 1; +if (common->utf && HAS_EXTRALEN(*cc)) + utflength += GET_EXTRALEN(*cc); + +do + { +#endif + + context->length -= IN_UCHARS(1); +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + + /* Unaligned read is supported. */ + if (othercasebit != 0 && othercasechar == cc) + { + context->c.asuchars[context->ucharptr] = *cc | othercasebit; + context->oc.asuchars[context->ucharptr] = othercasebit; + } + else + { + context->c.asuchars[context->ucharptr] = *cc; + context->oc.asuchars[context->ucharptr] = 0; + } + context->ucharptr++; + +#ifdef COMPILE_PCRE8 + if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) +#else + if (context->ucharptr >= 2 || context->length == 0) +#endif + { + if (context->length >= 4) + OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#ifdef COMPILE_PCRE8 + else if (context->length >= 2) + OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); + else if (context->length >= 1) + OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#else + else if (context->length >= 2) + OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#endif + context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; + + switch(context->ucharptr) + { + case 4 / sizeof(pcre_uchar): + if (context->oc.asint != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); + break; + + case 2 / sizeof(pcre_uchar): + if (context->oc.asushort != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); + break; + +#ifdef COMPILE_PCRE8 + case 1: + if (context->oc.asbyte != 0) + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); + break; +#endif + + default: + SLJIT_ASSERT_STOP(); + break; + } + context->ucharptr = 0; + } + +#else + + /* Unaligned read is unsupported. */ +#ifdef COMPILE_PCRE8 + if (context->length > 0) + OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#else + if (context->length > 0) + OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); +#endif + context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; + + if (othercasebit != 0 && othercasechar == cc) + { + OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); + } + else + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc)); + +#endif + + cc++; +#ifdef SUPPORT_UTF + utflength--; + } +while (utflength > 0); +#endif + +return cc; +} + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + +#define SET_TYPE_OFFSET(value) \ + if ((value) != typeoffset) \ + { \ + if ((value) > typeoffset) \ + OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \ + else \ + OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \ + } \ + typeoffset = (value); + +#define SET_CHAR_OFFSET(value) \ + if ((value) != charoffset) \ + { \ + if ((value) > charoffset) \ + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \ + else \ + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \ + } \ + charoffset = (value); + +static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) +{ +DEFINE_COMPILER; +jump_list *found = NULL; +jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks; +unsigned int c; +int compares; +struct sljit_jump *jump = NULL; +pcre_uchar *ccbegin; +#ifdef SUPPORT_UCP +BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; +BOOL charsaved = FALSE; +int typereg = TMP1, scriptreg = TMP1; +unsigned int typeoffset; +#endif +int invertcmp, numberofcmps; +unsigned int charoffset; + +/* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ +check_input_end(common, fallbacks); +read_char(common); + +if ((*cc++ & XCL_MAP) != 0) + { + OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); +#ifndef COMPILE_PCRE8 + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#elif defined SUPPORT_UTF + if (common->utf) + jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); +#endif + + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); + +#ifndef COMPILE_PCRE8 + JUMPHERE(jump); +#elif defined SUPPORT_UTF + if (common->utf) + JUMPHERE(jump); +#endif + OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); +#ifdef SUPPORT_UCP + charsaved = TRUE; +#endif + cc += 32 / sizeof(pcre_uchar); + } + +/* Scanning the necessary info. */ +ccbegin = cc; +compares = 0; +while (*cc != XCL_END) + { + compares++; + if (*cc == XCL_SINGLE) + { + cc += 2; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif +#ifdef SUPPORT_UCP + needschar = TRUE; +#endif + } + else if (*cc == XCL_RANGE) + { + cc += 2; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + cc++; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif +#ifdef SUPPORT_UCP + needschar = TRUE; +#endif + } +#ifdef SUPPORT_UCP + else + { + SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP); + cc++; + switch(*cc) + { + case PT_ANY: + break; + + case PT_LAMP: + case PT_GC: + case PT_PC: + case PT_ALNUM: + needstype = TRUE; + break; + + case PT_SC: + needsscript = TRUE; + break; + + case PT_SPACE: + case PT_PXSPACE: + case PT_WORD: + needstype = TRUE; + needschar = TRUE; + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } + cc += 2; + } +#endif + } + +#ifdef SUPPORT_UCP +/* Simple register allocation. TMP1 is preferred if possible. */ +if (needstype || needsscript) + { + if (needschar && !charsaved) + OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); + add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); + if (needschar) + { + if (needstype) + { + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); + typereg = RETURN_ADDR; + } + + if (needsscript) + scriptreg = TMP3; + OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); + } + else if (needstype && needsscript) + scriptreg = TMP3; + /* In all other cases only one of them was specified, and that can goes to TMP1. */ + + if (needsscript) + { + if (scriptreg == TMP1) + { + OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); + OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3); + } + else + { + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); + OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0); + } + } + } +#endif + +/* Generating code. */ +cc = ccbegin; +charoffset = 0; +numberofcmps = 0; +#ifdef SUPPORT_UCP +typeoffset = 0; +#endif + +while (*cc != XCL_END) + { + compares--; + invertcmp = (compares == 0 && list != fallbacks); + jump = NULL; + + if (*cc == XCL_SINGLE) + { + cc ++; +#ifdef SUPPORT_UTF + if (common->utf) + { + GETCHARINC(c, cc); + } + else +#endif + c = *cc++; + + if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); + COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + numberofcmps++; + } + else if (numberofcmps > 0) + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + numberofcmps = 0; + } + else + { + jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset); + numberofcmps = 0; + } + } + else if (*cc == XCL_RANGE) + { + cc ++; +#ifdef SUPPORT_UTF + if (common->utf) + { + GETCHARINC(c, cc); + } + else +#endif + c = *cc++; + SET_CHAR_OFFSET(c); +#ifdef SUPPORT_UTF + if (common->utf) + { + GETCHARINC(c, cc); + } + else +#endif + c = *cc++; + if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) + { + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); + COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); + numberofcmps++; + } + else if (numberofcmps > 0) + { + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); + jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + numberofcmps = 0; + } + else + { + jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset); + numberofcmps = 0; + } + } +#ifdef SUPPORT_UCP + else + { + if (*cc == XCL_NOTPROP) + invertcmp ^= 0x1; + cc++; + switch(*cc) + { + case PT_ANY: + if (list != fallbacks) + { + if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0)) + continue; + } + else if (cc[-1] == XCL_NOTPROP) + continue; + jump = JUMP(SLJIT_JUMP); + break; + + case PT_LAMP: + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); + COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + break; + + case PT_GC: + c = PRIV(ucp_typerange)[(int)cc[1] * 2]; + SET_TYPE_OFFSET(c); + jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); + break; + + case PT_PC: + jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset); + break; + + case PT_SC: + jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]); + break; + + case PT_SPACE: + case PT_PXSPACE: + if (*cc == PT_SPACE) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); + jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset); + } + SET_CHAR_OFFSET(9); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); + if (*cc == PT_SPACE) + JUMPHERE(jump); + + SET_TYPE_OFFSET(ucp_Zl); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); + jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + break; + + case PT_WORD: + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + /* ... fall through */ + + case PT_ALNUM: + SET_TYPE_OFFSET(ucp_Ll); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); + COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); + SET_TYPE_OFFSET(ucp_Nd); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); + jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); + break; + } + cc += 2; + } +#endif + + if (jump != NULL) + add_jump(compiler, compares > 0 ? list : fallbacks, jump); + } + +if (found != NULL) + set_jumps(found, LABEL()); +} + +#undef SET_TYPE_OFFSET +#undef SET_CHAR_OFFSET + +#endif + +static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks) +{ +DEFINE_COMPILER; +int length; +unsigned int c, oc, bit; +compare_context context; +struct sljit_jump *jump[4]; +#ifdef SUPPORT_UTF +struct sljit_label *label; +#ifdef SUPPORT_UCP +pcre_uchar propdata[5]; +#endif +#endif + +switch(type) + { + case OP_SOD: + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_SOM: + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0)); + return cc; + + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + return cc; + + case OP_NOT_DIGIT: + case OP_DIGIT: + check_input_end(common, fallbacks); + read_char8_type(common); + OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); + add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + return cc; + + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + check_input_end(common, fallbacks); + read_char8_type(common); + OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); + add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + return cc; + + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + check_input_end(common, fallbacks); + read_char8_type(common); + OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); + add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); + return cc; + + case OP_ANY: + check_input_end(common, fallbacks); + read_char(common); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); + jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); + JUMPHERE(jump[1]); + JUMPHERE(jump[0]); + } + else + check_newlinechar(common, common->nltype, fallbacks, TRUE); + return cc; + + case OP_ALLANY: + check_input_end(common, fallbacks); +#ifdef SUPPORT_UTF + if (common->utf) + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); +#ifdef COMPILE_PCRE8 + jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); +#else /* COMPILE_PCRE8 */ +#ifdef COMPILE_PCRE16 + jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); + OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); + COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); +#endif /* COMPILE_PCRE16 */ +#endif /* COMPILE_PCRE8 */ + JUMPHERE(jump[0]); + return cc; + } +#endif + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + return cc; + + case OP_ANYBYTE: + check_input_end(common, fallbacks); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + return cc; + +#ifdef SUPPORT_UTF +#ifdef SUPPORT_UCP + case OP_NOTPROP: + case OP_PROP: + propdata[0] = 0; + propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP; + propdata[2] = cc[0]; + propdata[3] = cc[1]; + propdata[4] = XCL_END; + compile_xclass_hotpath(common, propdata, fallbacks); + return cc + 2; +#endif +#endif + + case OP_ANYNL: + check_input_end(common, fallbacks); + read_char(common); + jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + jump[3] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[0]); + check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE); + JUMPHERE(jump[1]); + JUMPHERE(jump[2]); + JUMPHERE(jump[3]); + return cc; + + case OP_NOT_HSPACE: + case OP_HSPACE: + check_input_end(common, fallbacks); + read_char(common); + add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + return cc; + + case OP_NOT_VSPACE: + case OP_VSPACE: + check_input_end(common, fallbacks); + read_char(common); + add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); + return cc; + +#ifdef SUPPORT_UCP + case OP_EXTUNI: + check_input_end(common, fallbacks); + read_char(common); + add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc)); + + label = LABEL(); + jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); + read_char(common); + add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); + CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label); + + OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); + JUMPHERE(jump[0]); + return cc; +#endif + + case OP_EODN: + jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else if (common->nltype == NLTYPE_FIXED) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); + } + else + { + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); + jump[2] = JUMP(SLJIT_C_GREATER); + add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS)); + /* Equal. */ + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); + add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); + + JUMPHERE(jump[1]); + if (common->nltype == NLTYPE_ANYCRLF) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); + } + else + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0); + read_char(common); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); + } + JUMPHERE(jump[2]); + JUMPHERE(jump[3]); + } + JUMPHERE(jump[0]); + return cc; + + case OP_EOD: + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); + return cc; + + case OP_CIRC: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0)); + OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + return cc; + + case OP_CIRCM: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin)); + jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0); + OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, STR_PTR, 0, STR_END, 0)); + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + skip_char_back(common); + read_char(common); + check_newlinechar(common, common->nltype, fallbacks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + + case OP_DOLL: + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + + if (!common->endonly) + compile_char1_hotpath(common, OP_EODN, cc, fallbacks); + else + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); + return cc; + + case OP_DOLLM: + jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); + OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + jump[0] = JUMP(SLJIT_JUMP); + JUMPHERE(jump[1]); + + if (common->nltype == NLTYPE_FIXED && common->newline > 255) + { + OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); + } + else + { + peek_char(common); + check_newlinechar(common, common->nltype, fallbacks, FALSE); + } + JUMPHERE(jump[0]); + return cc; + + case OP_CHAR: + case OP_CHARI: + length = 1; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); +#endif + if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) + { + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); + + context.length = IN_UCHARS(length); + context.sourcereg = -1; +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + context.ucharptr = 0; +#endif + return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); + } + check_input_end(common, fallbacks); + read_char(common); +#ifdef SUPPORT_UTF + if (common->utf) + { + GETCHAR(c, cc); + } + else +#endif + c = *cc; + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); + return cc + length; + + case OP_NOT: + case OP_NOTI: + check_input_end(common, fallbacks); + length = 1; +#ifdef SUPPORT_UTF + if (common->utf) + { +#ifdef COMPILE_PCRE8 + c = *cc; + if (c < 128) + { + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + if (type == OP_NOT || !char_has_othercase(common, cc)) + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); + else + { + /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ + OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); + } + /* Skip the variable-length character. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + JUMPHERE(jump[0]); + return cc + 1; + } + else +#endif /* COMPILE_PCRE8 */ + { + GETCHARLEN(c, cc, length); + read_char(common); + } + } + else +#endif /* SUPPORT_UTF */ + { + read_char(common); + c = *cc; + } + + if (type == OP_NOT || !char_has_othercase(common, cc)) + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); + else + { + oc = char_othercase(common, c); + bit = c ^ oc; + if (ispowerof2(bit)) + { + OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); + } + else + { + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); + } + } + return cc + 1; + + case OP_CLASS: + case OP_NCLASS: + check_input_end(common, fallbacks); + read_char(common); +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + jump[0] = NULL; +#ifdef COMPILE_PCRE8 + /* This check only affects 8 bit mode. In other modes, we + always need to compare the value with 255. */ + if (common->utf) +#endif /* COMPILE_PCRE8 */ + { + jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); + if (type == OP_CLASS) + { + add_jump(compiler, fallbacks, jump[0]); + jump[0] = NULL; + } + } +#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ + OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); + OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); + OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); + OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); + OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); + add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + if (jump[0] != NULL) + JUMPHERE(jump[0]); +#endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ + return cc + 32 / sizeof(pcre_uchar); + +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 + case OP_XCLASS: + compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks); + return cc + GET(cc, 0) - 1; +#endif + + case OP_REVERSE: + length = GET(cc, 0); + SLJIT_ASSERT(length > 0); + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +#ifdef SUPPORT_UTF + if (common->utf) + { + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); + label = LABEL(); + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); + skip_char_back(common); + OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); + JUMPTO(SLJIT_C_NOT_ZERO, label); + return cc + LINK_SIZE; + } +#endif + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); + return cc + LINK_SIZE; + } +SLJIT_ASSERT_STOP(); +return cc; +} + +static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks) +{ +/* This function consumes at least one input character. */ +/* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ +DEFINE_COMPILER; +pcre_uchar *ccbegin = cc; +compare_context context; +int size; + +context.length = 0; +do + { + if (cc >= ccend) + break; + + if (*cc == OP_CHAR) + { + size = 1; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(cc[1])) + size += GET_EXTRALEN(cc[1]); +#endif + } + else if (*cc == OP_CHARI) + { + size = 1; +#ifdef SUPPORT_UTF + if (common->utf) + { + if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) + size = 0; + else if (HAS_EXTRALEN(cc[1])) + size += GET_EXTRALEN(cc[1]); + } + else +#endif + if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) + size = 0; + } + else + size = 0; + + cc += 1 + size; + context.length += IN_UCHARS(size); + } +while (size > 0 && context.length <= 128); + +cc = ccbegin; +if (context.length > 0) + { + /* We have a fixed-length byte sequence. */ + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length); + add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); + + context.sourcereg = -1; +#if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED + context.ucharptr = 0; +#endif + do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0); + return cc; + } + +/* A non-fixed length character will be checked if length == 0. */ +return compile_char1_hotpath(common, *cc, cc + 1, fallbacks); +} + +static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) +{ +DEFINE_COMPILER; +int offset = GET2(cc, 1) << 1; + +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); +if (!common->jscript_compat) + { + if (fallbacks == NULL) + { + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); + OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); + return JUMP(SLJIT_C_NOT_ZERO); + } + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); + } +return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); +} + +/* Forward definitions. */ +static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *); +static void compile_fallbackpath(compiler_common *, struct fallback_common *); + +#define PUSH_FALLBACK(size, ccstart, error) \ + do \ + { \ + fallback = sljit_alloc_memory(compiler, (size)); \ + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ + return error; \ + memset(fallback, 0, size); \ + fallback->prev = parent->top; \ + fallback->cc = (ccstart); \ + parent->top = fallback; \ + } \ + while (0) + +#define PUSH_FALLBACK_NOVALUE(size, ccstart) \ + do \ + { \ + fallback = sljit_alloc_memory(compiler, (size)); \ + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ + return; \ + memset(fallback, 0, size); \ + fallback->prev = parent->top; \ + fallback->cc = (ccstart); \ + parent->top = fallback; \ + } \ + while (0) + +#define FALLBACK_AS(type) ((type*)fallback) + +static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) +{ +DEFINE_COMPILER; +int offset = GET2(cc, 1) << 1; +struct sljit_jump *jump = NULL; + +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); +if (withchecks && !common->jscript_compat) + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); + +#if defined SUPPORT_UTF && defined SUPPORT_UCP +if (common->utf && *cc == OP_REFI) + { + SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + if (withchecks) + jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); + + /* Needed to save important temporary registers. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0); + sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); + } +else +#endif /* SUPPORT_UTF && SUPPORT_UCP */ + { + OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); + if (withchecks) + jump = JUMP(SLJIT_C_ZERO); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + + add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); + add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); + add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); + } + +if (jump != NULL) + { + if (emptyfail) + add_jump(compiler, fallbacks, jump); + else + JUMPHERE(jump); + } +return cc + 1 + IMM2_SIZE; +} + +static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; +pcre_uchar type; +struct sljit_label *label; +struct sljit_jump *zerolength; +struct sljit_jump *jump = NULL; +pcre_uchar *ccbegin = cc; +int min = 0, max = 0; +BOOL minimize; + +PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); + +type = cc[1 + IMM2_SIZE]; +minimize = (type & 0x1) != 0; +switch(type) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + min = 0; + max = 0; + cc += 1 + IMM2_SIZE + 1; + break; + case OP_CRPLUS: + case OP_CRMINPLUS: + min = 1; + max = 0; + cc += 1 + IMM2_SIZE + 1; + break; + case OP_CRQUERY: + case OP_CRMINQUERY: + min = 0; + max = 1; + cc += 1 + IMM2_SIZE + 1; + break; + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(cc, 1 + IMM2_SIZE + 1); + max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE); + cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE; + break; + default: + SLJIT_ASSERT_STOP(); + break; + } + +if (!minimize) + { + if (min == 0) + { + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); + /* Temporary release of STR_PTR. */ + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + zerolength = compile_ref_checks(common, ccbegin, NULL); + /* Restore if not zero length. */ + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + } + else + { + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); + } + + if (min > 1 || max > 1) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); + + label = LABEL(); + compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE); + + if (min > 1 || max > 1) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + if (min > 1) + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label); + if (max > 1) + { + jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max); + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); + JUMPHERE(jump); + } + } + + if (max == 0) + { + /* Includes min > 1 case as well. */ + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); + } + + JUMPHERE(zerolength); + FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); + + decrease_call_count(common); + return cc; + } + +allocate_stack(common, 2); +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); +if (type != OP_CRMINSTAR) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); + +if (min == 0) + { + zerolength = compile_ref_checks(common, ccbegin, NULL); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + jump = JUMP(SLJIT_JUMP); + } +else + zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks); + +FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); +if (max > 0) + add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max)); + +compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE); +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + +if (min > 1) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath); + } +else if (max > 0) + OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); + +if (jump != NULL) + JUMPHERE(jump); +JUMPHERE(zerolength); + +decrease_call_count(common); +return cc; +} + +static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; +recurse_entry *entry = common->entries; +recurse_entry *prev = NULL; +int start = GET(cc, 1); + +PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL); +while (entry != NULL) + { + if (entry->start == start) + break; + prev = entry; + entry = entry->next; + } + +if (entry == NULL) + { + entry = sljit_alloc_memory(compiler, sizeof(recurse_entry)); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + entry->next = NULL; + entry->entry = NULL; + entry->calls = NULL; + entry->start = start; + + if (prev != NULL) + prev->next = entry; + else + common->entries = entry; + } + +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); +allocate_stack(common, 1); +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); + +if (entry->entry == NULL) + add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL)); +else + JUMPTO(SLJIT_FAST_CALL, entry->entry); +/* Leave if the match is failed. */ +add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0)); +return cc + 1 + LINK_SIZE; +} + +static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional) +{ +DEFINE_COMPILER; +int framesize; +int localptr; +fallback_common altfallback; +pcre_uchar *ccbegin; +pcre_uchar opcode; +pcre_uchar bra = OP_BRA; +jump_list *tmp = NULL; +jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; +jump_list **found; +/* Saving previous accept variables. */ +struct sljit_label *save_acceptlabel = common->acceptlabel; +struct sljit_jump *jump; +struct sljit_jump *brajump = NULL; +jump_list *save_accept = common->accept; + +if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) + { + SLJIT_ASSERT(!conditional); + bra = *cc; + cc++; + } +localptr = PRIV_DATA(cc); +SLJIT_ASSERT(localptr != 0); +framesize = get_framesize(common, cc, FALSE); +fallback->framesize = framesize; +fallback->localptr = localptr; +opcode = *cc; +SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT); +found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target; +ccbegin = cc; +cc += GET(cc, 1); + +if (bra == OP_BRAMINZERO) + { + /* This is a braminzero fallback path. */ + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + } + +if (framesize < 0) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + } +else + { + allocate_stack(common, framesize + 2); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + init_frame(common, ccbegin, framesize + 1, 2, FALSE); + } + +memset(&altfallback, 0, sizeof(fallback_common)); +while (1) + { + common->acceptlabel = NULL; + common->accept = NULL; + altfallback.top = NULL; + altfallback.topfallbacks = NULL; + + if (*ccbegin == OP_ALT) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + + altfallback.cc = ccbegin; + compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + common->acceptlabel = save_acceptlabel; + common->accept = save_accept; + return NULL; + } + common->acceptlabel = LABEL(); + if (common->accept != NULL) + set_jumps(common->accept, common->acceptlabel); + + /* Reset stack. */ + if (framesize < 0) + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + else { + if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) + { + /* We don't need to keep the STR_PTR, only the previous localptr. */ + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); + } + else + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + } + } + + if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) + { + /* We know that STR_PTR was stored on the top of the stack. */ + if (conditional) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); + else if (bra == OP_BRAZERO) + { + if (framesize < 0) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); + } + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + else if (framesize >= 0) + { + /* For OP_BRA and OP_BRAMINZERO. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); + } + } + add_jump(compiler, found, JUMP(SLJIT_JUMP)); + + compile_fallbackpath(common, altfallback.top); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + common->acceptlabel = save_acceptlabel; + common->accept = save_accept; + return NULL; + } + set_jumps(altfallback.topfallbacks, LABEL()); + + if (*cc != OP_ALT) + break; + + ccbegin = cc; + cc += GET(cc, 1); + } +/* None of them matched. */ + +if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) + { + /* Assert is failed. */ + if (conditional || bra == OP_BRAZERO) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + + if (framesize < 0) + { + /* The topmost item should be 0. */ + if (bra == OP_BRAZERO) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + else + free_stack(common, 1); + } + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + /* The topmost item should be 0. */ + if (bra == OP_BRAZERO) + { + free_stack(common, framesize + 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + else + free_stack(common, framesize + 2); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); + } + jump = JUMP(SLJIT_JUMP); + if (bra != OP_BRAZERO) + add_jump(compiler, target, jump); + + /* Assert is successful. */ + set_jumps(tmp, LABEL()); + if (framesize < 0) + { + /* We know that STR_PTR was stored on the top of the stack. */ + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); + /* Keep the STR_PTR on the top of the stack. */ + if (bra == OP_BRAZERO) + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + else if (bra == OP_BRAMINZERO) + { + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + } + else + { + if (bra == OP_BRA) + { + /* We don't need to keep the STR_PTR, only the previous localptr. */ + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); + } + else + { + /* We don't need to keep the STR_PTR, only the previous localptr. */ + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); + } + } + + if (bra == OP_BRAZERO) + { + fallback->hotpath = LABEL(); + sljit_set_label(jump, fallback->hotpath); + } + else if (bra == OP_BRAMINZERO) + { + JUMPTO(SLJIT_JUMP, fallback->hotpath); + JUMPHERE(brajump); + if (framesize >= 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); + } + set_jumps(fallback->common.topfallbacks, LABEL()); + } + } +else + { + /* AssertNot is successful. */ + if (framesize < 0) + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (bra != OP_BRA) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + else + free_stack(common, 1); + } + else + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + /* The topmost item should be 0. */ + if (bra != OP_BRA) + { + free_stack(common, framesize + 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + else + free_stack(common, framesize + 2); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); + } + + if (bra == OP_BRAZERO) + fallback->hotpath = LABEL(); + else if (bra == OP_BRAMINZERO) + { + JUMPTO(SLJIT_JUMP, fallback->hotpath); + JUMPHERE(brajump); + } + + if (bra != OP_BRA) + { + SLJIT_ASSERT(found == &fallback->common.topfallbacks); + set_jumps(fallback->common.topfallbacks, LABEL()); + fallback->common.topfallbacks = NULL; + } + } + +common->acceptlabel = save_acceptlabel; +common->accept = save_accept; +return cc + 1 + LINK_SIZE; +} + +static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table) +{ +int condition = FALSE; +pcre_uchar *slotA = name_table; +pcre_uchar *slotB; +sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; +sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; +sljit_w no_capture; +int i; + +locals += OVECTOR_START / sizeof(sljit_w); +no_capture = locals[1]; + +for (i = 0; i < name_count; i++) + { + if (GET2(slotA, 0) == refno) break; + slotA += name_entry_size; + } + +if (i < name_count) + { + /* Found a name for the number - there can be only one; duplicate names + for different numbers are allowed, but not vice versa. First scan down + for duplicates. */ + + slotB = slotA; + while (slotB > name_table) + { + slotB -= name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = locals[GET2(slotB, 0) << 1] != no_capture; + if (condition) break; + } + else break; + } + + /* Scan up for duplicates */ + if (!condition) + { + slotB = slotA; + for (i++; i < name_count; i++) + { + slotB += name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = locals[GET2(slotB, 0) << 1] != no_capture; + if (condition) break; + } + else break; + } + } + } +return condition; +} + +static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table) +{ +int condition = FALSE; +pcre_uchar *slotA = name_table; +pcre_uchar *slotB; +sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; +sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; +sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)]; +int i; + +for (i = 0; i < name_count; i++) + { + if (GET2(slotA, 0) == recno) break; + slotA += name_entry_size; + } + +if (i < name_count) + { + /* Found a name for the number - there can be only one; duplicate + names for different numbers are allowed, but not vice versa. First + scan down for duplicates. */ + + slotB = slotA; + while (slotB > name_table) + { + slotB -= name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = GET2(slotB, 0) == group_num; + if (condition) break; + } + else break; + } + + /* Scan up for duplicates */ + if (!condition) + { + slotB = slotA; + for (i++; i < name_count; i++) + { + slotB += name_entry_size; + if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) + { + condition = GET2(slotB, 0) == group_num; + if (condition) break; + } + else break; + } + } + } +return condition; +} + +/* + Handling bracketed expressions is probably the most complex part. + + Stack layout naming characters: + S - Push the current STR_PTR + 0 - Push a 0 (NULL) + A - Push the current STR_PTR. Needed for restoring the STR_PTR + before the next alternative. Not pushed if there are no alternatives. + M - Any values pushed by the current alternative. Can be empty, or anything. + C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack. + L - Push the previous local (pointed by localptr) to the stack + () - opional values stored on the stack + ()* - optonal, can be stored multiple times + + The following list shows the regular expression templates, their PCRE byte codes + and stack layout supported by pcre-sljit. + + (?:) OP_BRA | OP_KET A M + () OP_CBRA | OP_KET C M + (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )* + OP_SBRA | OP_KETRMAX 0 L M S ( L M S )* + (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )* + OP_SBRA | OP_KETRMIN 0 L M S ( L M S )* + ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )* + OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )* + ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )* + OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )* + (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 ) + (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 ) + ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 ) + ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 ) + (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )* + OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )* + (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )* + OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )* + ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )* + OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )* + ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )* + OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )* + + + Stack layout naming characters: + A - Push the alternative index (starting from 0) on the stack. + Not pushed if there is no alternatives. + M - Any values pushed by the current alternative. Can be empty, or anything. + + The next list shows the possible content of a bracket: + (|) OP_*BRA | OP_ALT ... M A + (?()|) OP_*COND | OP_ALT M A + (?>|) OP_ONCE | OP_ALT ... [stack trace] M A + (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A + Or nothing, if trace is unnecessary +*/ + +static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; +pcre_uchar opcode; +int localptr = 0; +int offset = 0; +int stacksize; +pcre_uchar *ccbegin; +pcre_uchar *hotpath; +pcre_uchar bra = OP_BRA; +pcre_uchar ket; +assert_fallback *assert; +BOOL has_alternatives; +struct sljit_jump *jump; +struct sljit_jump *skip; +struct sljit_label *rmaxlabel = NULL; +struct sljit_jump *braminzerojump = NULL; + +PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); + +if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) + { + bra = *cc; + cc++; + opcode = *cc; + } + +opcode = *cc; +ccbegin = cc; +hotpath = ccbegin + 1 + LINK_SIZE; + +if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) + { + /* Drop this bracket_fallback. */ + parent->top = fallback->prev; + return bracketend(cc); + } + +ket = *(bracketend(cc) - 1 - LINK_SIZE); +SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); +SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); +cc += GET(cc, 1); + +has_alternatives = *cc == OP_ALT; +if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) + { + has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE; + if (*hotpath == OP_NRREF) + { + stacksize = GET2(hotpath, 1); + if (common->currententry == NULL || stacksize == RREF_ANY) + has_alternatives = FALSE; + else if (common->currententry->start == 0) + has_alternatives = stacksize != 0; + else + has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE); + } + } + +if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) + opcode = OP_SCOND; +if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) + opcode = OP_ONCE; + +if (opcode == OP_CBRA || opcode == OP_SCBRA) + { + /* Capturing brackets has a pre-allocated space. */ + offset = GET2(ccbegin, 1 + LINK_SIZE); + localptr = OVECTOR_PRIV(offset); + offset <<= 1; + FALLBACK_AS(bracket_fallback)->localptr = localptr; + hotpath += IMM2_SIZE; + } +else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) + { + /* Other brackets simply allocate the next entry. */ + localptr = PRIV_DATA(ccbegin); + SLJIT_ASSERT(localptr != 0); + FALLBACK_AS(bracket_fallback)->localptr = localptr; + if (opcode == OP_ONCE) + FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE); + } + +/* Instructions before the first alternative. */ +stacksize = 0; +if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) + stacksize++; +if (bra == OP_BRAZERO) + stacksize++; + +if (stacksize > 0) + allocate_stack(common, stacksize); + +stacksize = 0; +if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); + stacksize++; + } + +if (bra == OP_BRAZERO) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); + +if (bra == OP_BRAMINZERO) + { + /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */ + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (ket != OP_KETRMIN) + { + free_stack(common, 1); + braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + } + else + { + if (opcode == OP_ONCE || opcode >= OP_SBRA) + { + jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + /* Nothing stored during the first run. */ + skip = JUMP(SLJIT_JUMP); + JUMPHERE(jump); + /* Checking zero-length iteration. */ + if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0) + { + /* When we come from outside, localptr contains the previous STR_PTR. */ + braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + } + else + { + /* Except when the whole stack frame must be saved. */ + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w)); + } + JUMPHERE(skip); + } + else + { + jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + JUMPHERE(jump); + } + } + } + +if (ket == OP_KETRMIN) + FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); + +if (ket == OP_KETRMAX) + { + rmaxlabel = LABEL(); + if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA) + FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel; + } + +/* Handling capturing brackets and alternatives. */ +if (opcode == OP_ONCE) + { + if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) + { + /* Neither capturing brackets nor recursions are not found in the block. */ + if (ket == OP_KETRMIN) + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); + OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + } + else if (ket == OP_KETRMAX || has_alternatives) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + } + else + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); + } + else + { + if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) + { + allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE); + } + else + { + allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); + init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE); + } + } + } +else if (opcode == OP_CBRA || opcode == OP_SCBRA) + { + /* Saving the previous values. */ + allocate_stack(common, 3); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); + } +else if (opcode == OP_SBRA || opcode == OP_SCOND) + { + /* Saving the previous value. */ + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); + } +else if (has_alternatives) + { + /* Pushing the starting string pointer. */ + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + } + +/* Generating code for the first alternative. */ +if (opcode == OP_COND || opcode == OP_SCOND) + { + if (*hotpath == OP_CREF) + { + SLJIT_ASSERT(has_alternatives); + add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), + CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); + hotpath += 1 + IMM2_SIZE; + } + else if (*hotpath == OP_NCREF) + { + SLJIT_ASSERT(has_alternatives); + stacksize = GET2(hotpath, 1); + jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); + + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); + sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); + add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); + + JUMPHERE(jump); + hotpath += 1 + IMM2_SIZE; + } + else if (*hotpath == OP_RREF || *hotpath == OP_NRREF) + { + /* Never has other case. */ + FALLBACK_AS(bracket_fallback)->u.condfailed = NULL; + + stacksize = GET2(hotpath, 1); + if (common->currententry == NULL) + stacksize = 0; + else if (stacksize == RREF_ANY) + stacksize = 1; + else if (common->currententry->start == 0) + stacksize = stacksize == 0; + else + stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); + + if (*hotpath == OP_RREF || stacksize || common->currententry == NULL) + { + SLJIT_ASSERT(!has_alternatives); + if (stacksize != 0) + hotpath += 1 + IMM2_SIZE; + else + { + if (*cc == OP_ALT) + { + hotpath = cc + 1 + LINK_SIZE; + cc += GET(cc, 1); + } + else + hotpath = cc; + } + } + else + { + SLJIT_ASSERT(has_alternatives); + + stacksize = GET2(hotpath, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); + OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); + sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); + add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); + hotpath += 1 + IMM2_SIZE; + } + } + else + { + SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT); + /* Similar code as PUSH_FALLBACK macro. */ + assert = sljit_alloc_memory(compiler, sizeof(assert_fallback)); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + memset(assert, 0, sizeof(assert_fallback)); + assert->common.cc = hotpath; + FALLBACK_AS(bracket_fallback)->u.assert = assert; + hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE); + } + } + +compile_hotpath(common, hotpath, cc, fallback); +if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + +if (opcode == OP_ONCE) + { + if (FALLBACK_AS(bracket_fallback)->u.framesize < 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + /* TMP2 which is set here used by OP_KETRMAX below. */ + if (ket == OP_KETRMAX) + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); + else if (ket == OP_KETRMIN) + { + /* Move the STR_PTR to the localptr. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); + } + } + else + { + stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w)); + if (ket == OP_KETRMAX) + { + /* TMP2 which is set here used by OP_KETRMAX below. */ + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + } + } + +stacksize = 0; +if (ket != OP_KET || bra != OP_BRA) + stacksize++; +if (has_alternatives && opcode != OP_ONCE) + stacksize++; + +if (stacksize > 0) + allocate_stack(common, stacksize); + +stacksize = 0; +if (ket != OP_KET) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); + stacksize++; + } +else if (bra != OP_BRA) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); + stacksize++; + } + +if (has_alternatives) + { + if (opcode != OP_ONCE) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); + if (ket != OP_KETRMAX) + FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); + } + +/* Must be after the hotpath label. */ +if (offset != 0) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); + } + +if (ket == OP_KETRMAX) + { + if (opcode == OP_ONCE || opcode >= OP_SBRA) + { + if (has_alternatives) + FALLBACK_AS(bracket_fallback)->althotpath = LABEL(); + /* Checking zero-length iteration. */ + if (opcode != OP_ONCE) + CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel); + else + /* TMP2 must contain the starting STR_PTR. */ + CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel); + } + else + JUMPTO(SLJIT_JUMP, rmaxlabel); + FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL(); + } + +if (bra == OP_BRAZERO) + FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL(); + +if (bra == OP_BRAMINZERO) + { + /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ + JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath); + if (braminzerojump != NULL) + { + JUMPHERE(braminzerojump); + /* We need to release the end pointer to perform the + fallback for the zero-length iteration. When + framesize is < 0, OP_ONCE will do the release itself. */ + if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + } + else if (ket == OP_KETRMIN && opcode != OP_ONCE) + free_stack(common, 1); + } + /* Continue to the normal fallback. */ + } + +if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO) + decrease_call_count(common); + +/* Skip the other alternatives. */ +while (*cc == OP_ALT) + cc += GET(cc, 1); +cc += 1 + LINK_SIZE; +return cc; +} + +static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; +pcre_uchar opcode; +int localptr; +int cbraprivptr = 0; +int framesize; +int stacksize; +int offset = 0; +BOOL zero = FALSE; +pcre_uchar *ccbegin = NULL; +int stack; +struct sljit_label *loop = NULL; +struct jump_list *emptymatch = NULL; + +PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL); +if (*cc == OP_BRAPOSZERO) + { + zero = TRUE; + cc++; + } + +opcode = *cc; +localptr = PRIV_DATA(cc); +SLJIT_ASSERT(localptr != 0); +FALLBACK_AS(bracketpos_fallback)->localptr = localptr; +switch(opcode) + { + case OP_BRAPOS: + case OP_SBRAPOS: + ccbegin = cc + 1 + LINK_SIZE; + break; + + case OP_CBRAPOS: + case OP_SCBRAPOS: + offset = GET2(cc, 1 + LINK_SIZE); + cbraprivptr = OVECTOR_PRIV(offset); + offset <<= 1; + ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE; + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } + +framesize = get_framesize(common, cc, FALSE); +FALLBACK_AS(bracketpos_fallback)->framesize = framesize; +if (framesize < 0) + { + stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; + if (!zero) + stacksize++; + FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; + allocate_stack(common, stacksize); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0); + + if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); + } + else + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + + if (!zero) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1); + } +else + { + stacksize = framesize + 1; + if (!zero) + stacksize++; + if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) + stacksize++; + FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize; + allocate_stack(common, stacksize); + + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0); + stack = 0; + if (!zero) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); + stack++; + } + if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); + stack++; + } + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); + init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE); + } + +if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + +loop = LABEL(); +while (*cc != OP_KETRPOS) + { + fallback->top = NULL; + fallback->topfallbacks = NULL; + cc += GET(cc, 1); + + compile_hotpath(common, ccbegin, cc, fallback); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + + if (framesize < 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + + if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + } + else + { + if (opcode == OP_SBRAPOS) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + } + + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) + add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); + + if (!zero) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); + } + else + { + if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + { + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + } + else + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w)); + if (opcode == OP_SBRAPOS) + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0); + } + + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) + add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); + + if (!zero) + { + if (framesize < 0) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); + else + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + } + JUMPTO(SLJIT_JUMP, loop); + flush_stubs(common); + + compile_fallbackpath(common, fallback->top); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return NULL; + set_jumps(fallback->topfallbacks, LABEL()); + + if (framesize < 0) + { + if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + else + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + else + { + if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) + { + /* Last alternative. */ + if (*cc == OP_KETRPOS) + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); + } + else + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); + } + } + + if (*cc == OP_KETRPOS) + break; + ccbegin = cc + 1 + LINK_SIZE; + } + +fallback->topfallbacks = NULL; +if (!zero) + { + if (framesize < 0) + add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0)); + else /* TMP2 is set to [localptr] above. */ + add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0)); + } + +/* None of them matched. */ +set_jumps(emptymatch, LABEL()); +decrease_call_count(common); +return cc + 1 + LINK_SIZE; +} + +static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end) +{ +int class_len; + +*opcode = *cc; +if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO) + { + cc++; + *type = OP_CHAR; + } +else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI) + { + cc++; + *type = OP_CHARI; + *opcode -= OP_STARI - OP_STAR; + } +else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO) + { + cc++; + *type = OP_NOT; + *opcode -= OP_NOTSTAR - OP_STAR; + } +else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI) + { + cc++; + *type = OP_NOTI; + *opcode -= OP_NOTSTARI - OP_STAR; + } +else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO) + { + cc++; + *opcode -= OP_TYPESTAR - OP_STAR; + *type = 0; + } +else + { + SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); + *type = *opcode; + cc++; + class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); + *opcode = cc[class_len - 1]; + if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) + { + *opcode -= OP_CRSTAR - OP_STAR; + if (end != NULL) + *end = cc + class_len; + } + else + { + SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE); + *arg1 = GET2(cc, (class_len + IMM2_SIZE)); + *arg2 = GET2(cc, class_len); + + if (*arg2 == 0) + { + SLJIT_ASSERT(*arg1 != 0); + *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO; + } + if (*arg1 == *arg2) + *opcode = OP_EXACT; + + if (end != NULL) + *end = cc + class_len + 2 * IMM2_SIZE; + } + return cc; + } + +if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO) + { + *arg1 = GET2(cc, 0); + cc += IMM2_SIZE; + } + +if (*type == 0) + { + *type = *cc; + if (end != NULL) + *end = next_opcode(common, cc); + cc++; + return cc; + } + +if (end != NULL) + { + *end = cc + 1; +#ifdef SUPPORT_UTF + if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); +#endif + } +return cc; +} + +static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; +pcre_uchar opcode; +pcre_uchar type; +int arg1 = -1, arg2 = -1; +pcre_uchar* end; +jump_list *nomatch = NULL; +struct sljit_jump *jump = NULL; +struct sljit_label *label; + +PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); + +cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); + +switch(opcode) + { + case OP_STAR: + case OP_PLUS: + case OP_UPTO: + case OP_CRRANGE: + if (type == OP_ANYNL || type == OP_EXTUNI) + { + if (opcode == OP_STAR || opcode == OP_UPTO) + { + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0); + } + else + { + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + } + if (opcode == OP_UPTO || opcode == OP_CRRANGE) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0); + + label = LABEL(); + compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); + if (opcode == OP_UPTO || opcode == OP_CRRANGE) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + if (opcode == OP_CRRANGE && arg2 > 0) + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label); + if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0)) + jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + } + + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); + if (jump != NULL) + JUMPHERE(jump); + } + else + { + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); + label = LABEL(); + compile_char1_hotpath(common, type, cc, &nomatch); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0)) + { + OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); + JUMPTO(SLJIT_JUMP, label); + } + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); + } + set_jumps(nomatch, LABEL()); + if (opcode == OP_PLUS || opcode == OP_CRRANGE) + add_jump(compiler, &fallback->topfallbacks, + CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); + break; + + case OP_MINSTAR: + case OP_MINPLUS: + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + if (opcode == OP_MINPLUS) + add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); + FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); + break; + + case OP_MINUPTO: + case OP_CRMINRANGE: + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); + if (opcode == OP_CRMINRANGE) + add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); + FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); + break; + + case OP_QUERY: + case OP_MINQUERY: + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + if (opcode == OP_QUERY) + compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); + FALLBACK_AS(iterator_fallback)->hotpath = LABEL(); + break; + + case OP_EXACT: + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); + label = LABEL(); + compile_char1_hotpath(common, type, cc, &fallback->topfallbacks); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); + break; + + case OP_POSSTAR: + case OP_POSPLUS: + case OP_POSUPTO: + if (opcode != OP_POSSTAR) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); + label = LABEL(); + compile_char1_hotpath(common, type, cc, &nomatch); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); + if (opcode != OP_POSUPTO) + { + if (opcode == OP_POSPLUS) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2); + JUMPTO(SLJIT_JUMP, label); + } + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0); + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label); + } + set_jumps(nomatch, LABEL()); + if (opcode == OP_POSPLUS) + add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2)); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); + break; + + case OP_POSQUERY: + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); + compile_char1_hotpath(common, type, cc, &nomatch); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0); + set_jumps(nomatch, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } + +decrease_call_count(common); +return end; +} + +static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; + +PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL); + +if (*cc == OP_FAIL) + { + add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); + return cc + 1; + } + +if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL) + { + /* No need to check notempty conditions. */ + if (common->acceptlabel == NULL) + add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); + else + JUMPTO(SLJIT_JUMP, common->acceptlabel); + return cc + 1; + } + +if (common->acceptlabel == NULL) + add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0))); +else + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel); +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); +add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); +OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); +if (common->acceptlabel == NULL) + add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); +else + CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); +if (common->acceptlabel == NULL) + add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); +else + CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); +add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP)); +return cc + 1; +} + +static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc) +{ +DEFINE_COMPILER; +int offset = GET2(cc, 1); + +/* Data will be discarded anyway... */ +if (common->currententry != NULL) + return cc + 1 + IMM2_SIZE; + +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset)); +offset <<= 1; +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); +return cc + 1 + IMM2_SIZE; +} + +static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent) +{ +DEFINE_COMPILER; +fallback_common *fallback; + +while (cc < ccend) + { + switch(*cc) + { + case OP_SOD: + case OP_SOM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + case OP_ANYBYTE: + case OP_NOTPROP: + case OP_PROP: + case OP_ANYNL: + case OP_NOT_HSPACE: + case OP_HSPACE: + case OP_NOT_VSPACE: + case OP_VSPACE: + case OP_EXTUNI: + case OP_EODN: + case OP_EOD: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + case OP_NOT: + case OP_NOTI: + case OP_REVERSE: + cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); + break; + + case OP_SET_SOM: + PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc); + allocate_stack(common, 1); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); + cc++; + break; + + case OP_CHAR: + case OP_CHARI: + cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); + break; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + case OP_EXACT: + case OP_POSSTAR: + case OP_POSPLUS: + case OP_POSQUERY: + case OP_POSUPTO: + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_UPTOI: + case OP_MINUPTOI: + case OP_EXACTI: + case OP_POSSTARI: + case OP_POSPLUSI: + case OP_POSQUERYI: + case OP_POSUPTOI: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTEXACT: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + case OP_NOTPOSQUERY: + case OP_NOTPOSUPTO: + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTEXACTI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERYI: + case OP_NOTPOSUPTOI: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + case OP_TYPEPOSUPTO: + cc = compile_iterator_hotpath(common, cc, parent); + break; + + case OP_CLASS: + case OP_NCLASS: + if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE) + cc = compile_iterator_hotpath(common, cc, parent); + else + cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); + break; + +#if defined SUPPORT_UTF || defined COMPILE_PCRE16 + case OP_XCLASS: + if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) + cc = compile_iterator_hotpath(common, cc, parent); + else + cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); + break; +#endif + + case OP_REF: + case OP_REFI: + if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE) + cc = compile_ref_iterator_hotpath(common, cc, parent); + else + cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE); + break; + + case OP_RECURSE: + cc = compile_recurse_hotpath(common, cc, parent); + break; + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); + cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); + break; + + case OP_BRAMINZERO: + PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc); + cc = bracketend(cc + 1); + if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN) + { + allocate_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + } + else + { + allocate_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); + } + FALLBACK_AS(braminzero_fallback)->hotpath = LABEL(); + if (cc[1] > OP_ASSERTBACK_NOT) + decrease_call_count(common); + break; + + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRA: + case OP_CBRA: + case OP_COND: + case OP_SBRA: + case OP_SCBRA: + case OP_SCOND: + cc = compile_bracket_hotpath(common, cc, parent); + break; + + case OP_BRAZERO: + if (cc[1] > OP_ASSERTBACK_NOT) + cc = compile_bracket_hotpath(common, cc, parent); + else + { + PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc); + cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE); + } + break; + + case OP_BRAPOS: + case OP_CBRAPOS: + case OP_SBRAPOS: + case OP_SCBRAPOS: + case OP_BRAPOSZERO: + cc = compile_bracketpos_hotpath(common, cc, parent); + break; + + case OP_FAIL: + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + cc = compile_fail_accept_hotpath(common, cc, parent); + break; + + case OP_CLOSE: + cc = compile_close_hotpath(common, cc); + break; + + case OP_SKIPZERO: + cc = bracketend(cc + 1); + break; + + default: + SLJIT_ASSERT_STOP(); + return; + } + if (cc == NULL) + return; + } +SLJIT_ASSERT(cc == ccend); +} + +#undef PUSH_FALLBACK +#undef PUSH_FALLBACK_NOVALUE +#undef FALLBACK_AS + +#define COMPILE_FALLBACKPATH(current) \ + do \ + { \ + compile_fallbackpath(common, (current)); \ + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \ + return; \ + } \ + while (0) + +#define CURRENT_AS(type) ((type*)current) + +static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; +pcre_uchar *cc = current->cc; +pcre_uchar opcode; +pcre_uchar type; +int arg1 = -1, arg2 = -1; +struct sljit_label *label = NULL; +struct sljit_jump *jump = NULL; + +cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL); + +switch(opcode) + { + case OP_STAR: + case OP_PLUS: + case OP_UPTO: + case OP_CRRANGE: + if (type == OP_ANYNL || type == OP_EXTUNI) + { + set_jumps(current->topfallbacks, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); + } + else + { + if (opcode == OP_STAR || opcode == OP_UPTO) + arg2 = 0; + else if (opcode == OP_PLUS) + arg2 = 1; + jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1); + OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + skip_char_back(common); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); + if (opcode == OP_PLUS || opcode == OP_CRRANGE) + set_jumps(current->topfallbacks, LABEL()); + JUMPHERE(jump); + free_stack(common, 2); + } + break; + + case OP_MINSTAR: + case OP_MINPLUS: + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (opcode == OP_MINPLUS) + { + set_jumps(current->topfallbacks, LABEL()); + current->topfallbacks = NULL; + } + compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); + set_jumps(current->topfallbacks, LABEL()); + free_stack(common, 1); + break; + + case OP_MINUPTO: + case OP_CRMINRANGE: + if (opcode == OP_CRMINRANGE) + { + set_jumps(current->topfallbacks, LABEL()); + current->topfallbacks = NULL; + label = LABEL(); + } + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); + + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); + + if (opcode == OP_CRMINRANGE) + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label); + + if (opcode == OP_CRMINRANGE && arg1 == 0) + JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); + else + CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath); + + set_jumps(current->topfallbacks, LABEL()); + free_stack(common, 2); + break; + + case OP_QUERY: + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); + jump = JUMP(SLJIT_JUMP); + set_jumps(current->topfallbacks, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); + JUMPHERE(jump); + free_stack(common, 1); + break; + + case OP_MINQUERY: + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + compile_char1_hotpath(common, type, cc, ¤t->topfallbacks); + JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath); + set_jumps(current->topfallbacks, LABEL()); + JUMPHERE(jump); + free_stack(common, 1); + break; + + case OP_EXACT: + case OP_POSPLUS: + set_jumps(current->topfallbacks, LABEL()); + break; + + case OP_POSSTAR: + case OP_POSQUERY: + case OP_POSUPTO: + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } +} + +static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; +pcre_uchar *cc = current->cc; +pcre_uchar type; + +type = cc[1 + IMM2_SIZE]; +if ((type & 0x1) == 0) + { + set_jumps(current->topfallbacks, LABEL()); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); + return; + } + +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); +CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath); +set_jumps(current->topfallbacks, LABEL()); +free_stack(common, 2); +} + +static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; + +set_jumps(current->topfallbacks, LABEL()); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); +free_stack(common, 1); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); +} + +static void compile_assert_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; +pcre_uchar *cc = current->cc; +pcre_uchar bra = OP_BRA; +struct sljit_jump *brajump = NULL; + +SLJIT_ASSERT(*cc != OP_BRAMINZERO); +if (*cc == OP_BRAZERO) + { + bra = *cc; + cc++; + } + +if (bra == OP_BRAZERO) + { + SLJIT_ASSERT(current->topfallbacks == NULL); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + +if (CURRENT_AS(assert_fallback)->framesize < 0) + { + set_jumps(current->topfallbacks, LABEL()); + + if (bra == OP_BRAZERO) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath); + free_stack(common, 1); + } + return; + } + +if (bra == OP_BRAZERO) + { + if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT) + { + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath); + free_stack(common, 1); + return; + } + free_stack(common, 1); + brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0); + } + +if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w)); + + set_jumps(current->topfallbacks, LABEL()); + } +else + set_jumps(current->topfallbacks, LABEL()); + +if (bra == OP_BRAZERO) + { + /* We know there is enough place on the stack. */ + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); + JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath); + JUMPHERE(brajump); + } +} + +static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; +int opcode; +int offset = 0; +int localptr = CURRENT_AS(bracket_fallback)->localptr; +int stacksize; +int count; +pcre_uchar *cc = current->cc; +pcre_uchar *ccbegin; +pcre_uchar *ccprev; +jump_list *jumplist = NULL; +jump_list *jumplistitem = NULL; +pcre_uchar bra = OP_BRA; +pcre_uchar ket; +assert_fallback *assert; +BOOL has_alternatives; +struct sljit_jump *brazero = NULL; +struct sljit_jump *once = NULL; +struct sljit_jump *cond = NULL; +struct sljit_label *rminlabel = NULL; + +if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) + { + bra = *cc; + cc++; + } + +opcode = *cc; +ccbegin = cc; +ket = *(bracketend(ccbegin) - 1 - LINK_SIZE); +cc += GET(cc, 1); +has_alternatives = *cc == OP_ALT; +if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) + has_alternatives = (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) || CURRENT_AS(bracket_fallback)->u.condfailed != NULL; +if (opcode == OP_CBRA || opcode == OP_SCBRA) + offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1; +if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) + opcode = OP_SCOND; +if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) + opcode = OP_ONCE; + +if (ket == OP_KETRMAX) + { + if (bra != OP_BRAZERO) + free_stack(common, 1); + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0); + } + } +else if (ket == OP_KETRMIN) + { + if (bra != OP_BRAMINZERO) + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + if (opcode >= OP_SBRA || opcode == OP_ONCE) + { + /* Checking zero-length iteration. */ + if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0) + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath); + else + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath); + } + if (opcode != OP_ONCE) + free_stack(common, 1); + } + else + JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath); + } + rminlabel = LABEL(); + } +else if (bra == OP_BRAZERO) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); + } + +if (SLJIT_UNLIKELY(opcode == OP_ONCE)) + { + if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + } + once = JUMP(SLJIT_JUMP); + } +else if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) + { + if (has_alternatives) + { + /* Always exactly one alternative. */ + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + + jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list)); + if (SLJIT_UNLIKELY(!jumplistitem)) + return; + jumplist = jumplistitem; + jumplistitem->next = NULL; + jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1); + } + } +else if (*cc == OP_ALT) + { + /* Build a jump list. Get the last successfully matched branch index. */ + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + count = 1; + do + { + /* Append as the last item. */ + if (jumplist != NULL) + { + jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list)); + jumplistitem = jumplistitem->next; + } + else + { + jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list)); + jumplist = jumplistitem; + } + + if (SLJIT_UNLIKELY(!jumplistitem)) + return; + + jumplistitem->next = NULL; + jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++); + cc += GET(cc, 1); + } + while (*cc == OP_ALT); + + cc = ccbegin + GET(ccbegin, 1); + } + +COMPILE_FALLBACKPATH(current->top); +if (current->topfallbacks) + set_jumps(current->topfallbacks, LABEL()); + +if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) + { + /* Conditional block always has at most one alternative. */ + if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT) + { + SLJIT_ASSERT(has_alternatives); + assert = CURRENT_AS(bracket_fallback)->u.assert; + if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK)) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); + } + cond = JUMP(SLJIT_JUMP); + set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL()); + } + else if (CURRENT_AS(bracket_fallback)->u.condfailed != NULL) + { + SLJIT_ASSERT(has_alternatives); + cond = JUMP(SLJIT_JUMP); + set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL()); + } + else + SLJIT_ASSERT(!has_alternatives); + } + +if (has_alternatives) + { + count = 1; + do + { + current->top = NULL; + current->topfallbacks = NULL; + current->nextfallbacks = NULL; + if (*cc == OP_ALT) + { + ccprev = cc + 1 + LINK_SIZE; + cc += GET(cc, 1); + if (opcode != OP_COND && opcode != OP_SCOND) + { + if (localptr != 0 && opcode != OP_ONCE) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + else + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + compile_hotpath(common, ccprev, cc, current); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return; + } + + /* Instructions after the current alternative is succesfully matched. */ + /* There is a similar code in compile_bracket_hotpath. */ + if (opcode == OP_ONCE) + { + if (CURRENT_AS(bracket_fallback)->u.framesize < 0) + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + /* TMP2 which is set here used by OP_KETRMAX below. */ + if (ket == OP_KETRMAX) + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); + else if (ket == OP_KETRMIN) + { + /* Move the STR_PTR to the localptr. */ + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); + } + } + else + { + OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (CURRENT_AS(bracket_fallback)->u.framesize + 2) * sizeof(sljit_w)); + if (ket == OP_KETRMAX) + { + /* TMP2 which is set here used by OP_KETRMAX below. */ + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + } + } + } + + stacksize = 0; + if (opcode != OP_ONCE) + stacksize++; + if (ket != OP_KET || bra != OP_BRA) + stacksize++; + + if (stacksize > 0) { + if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0) + allocate_stack(common, stacksize); + else + { + /* We know we have place at least for one item on the top of the stack. */ + SLJIT_ASSERT(stacksize == 1); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); + } + } + + stacksize = 0; + if (ket != OP_KET || bra != OP_BRA) + { + if (ket != OP_KET) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); + else + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); + stacksize++; + } + + if (opcode != OP_ONCE) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); + + if (offset != 0) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); + } + + JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath); + + if (opcode != OP_ONCE) + { + SLJIT_ASSERT(jumplist); + JUMPHERE(jumplist->jump); + jumplist = jumplist->next; + } + + COMPILE_FALLBACKPATH(current->top); + if (current->topfallbacks) + set_jumps(current->topfallbacks, LABEL()); + SLJIT_ASSERT(!current->nextfallbacks); + } + while (*cc == OP_ALT); + SLJIT_ASSERT(!jumplist); + + if (cond != NULL) + { + SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); + assert = CURRENT_AS(bracket_fallback)->u.assert; + if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) + + { + OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w)); + } + JUMPHERE(cond); + } + + /* Free the STR_PTR. */ + if (localptr == 0) + free_stack(common, 1); + } + +if (offset != 0) + { + /* Using both tmp register is better for instruction scheduling. */ + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(2)); + free_stack(common, 3); + } +else if (opcode == OP_SBRA || opcode == OP_SCOND) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + } +else if (opcode == OP_ONCE) + { + cc = ccbegin + GET(ccbegin, 1); + if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) + { + /* Reset head and drop saved frame. */ + stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; + free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize); + } + else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) + { + /* The STR_PTR must be released. */ + free_stack(common, 1); + } + + JUMPHERE(once); + /* Restore previous localptr */ + if (CURRENT_AS(bracket_fallback)->u.framesize >= 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w)); + else if (ket == OP_KETRMIN) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + /* See the comment below. */ + free_stack(common, 2); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); + } + } + +if (ket == OP_KETRMAX) + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_fallback)->recursivehotpath); + if (bra == OP_BRAZERO) + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath); + JUMPHERE(brazero); + } + free_stack(common, 1); + } +else if (ket == OP_KETRMIN) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + + /* OP_ONCE removes everything in case of a fallback, so we don't + need to explicitly release the STR_PTR. The extra release would + affect badly the free_stack(2) above. */ + if (opcode != OP_ONCE) + free_stack(common, 1); + CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel); + if (opcode == OP_ONCE) + free_stack(common, bra == OP_BRAMINZERO ? 2 : 1); + else if (bra == OP_BRAMINZERO) + free_stack(common, 1); + } +else if (bra == OP_BRAZERO) + { + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath); + JUMPHERE(brazero); + } +} + +static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; +int offset; +struct sljit_jump *jump; + +if (CURRENT_AS(bracketpos_fallback)->framesize < 0) + { + if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS) + { + offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1; + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); + } + set_jumps(current->topfallbacks, LABEL()); + free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize); + return; + } + +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr); +add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + +if (current->topfallbacks) + { + jump = JUMP(SLJIT_JUMP); + set_jumps(current->topfallbacks, LABEL()); + /* Drop the stack frame. */ + free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize); + JUMPHERE(jump); + } +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w)); +} + +static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +assert_fallback fallback; + +current->top = NULL; +current->topfallbacks = NULL; +current->nextfallbacks = NULL; +if (current->cc[1] > OP_ASSERTBACK_NOT) + { + /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */ + compile_bracket_hotpath(common, current->cc, current); + compile_bracket_fallbackpath(common, current->top); + } +else + { + memset(&fallback, 0, sizeof(fallback)); + fallback.common.cc = current->cc; + fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath; + /* Manual call of compile_assert_hotpath. */ + compile_assert_hotpath(common, current->cc, &fallback, FALSE); + } +SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks); +} + +static void compile_fallbackpath(compiler_common *common, struct fallback_common *current) +{ +DEFINE_COMPILER; + +while (current) + { + if (current->nextfallbacks != NULL) + set_jumps(current->nextfallbacks, LABEL()); + switch(*current->cc) + { + case OP_SET_SOM: + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + free_stack(common, 1); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0); + break; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_QUERY: + case OP_MINQUERY: + case OP_UPTO: + case OP_MINUPTO: + case OP_EXACT: + case OP_POSSTAR: + case OP_POSPLUS: + case OP_POSQUERY: + case OP_POSUPTO: + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_UPTOI: + case OP_MINUPTOI: + case OP_EXACTI: + case OP_POSSTARI: + case OP_POSPLUSI: + case OP_POSQUERYI: + case OP_POSUPTOI: + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTEXACT: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + case OP_NOTPOSQUERY: + case OP_NOTPOSUPTO: + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTEXACTI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERYI: + case OP_NOTPOSUPTOI: + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + case OP_TYPEPOSQUERY: + case OP_TYPEPOSUPTO: + case OP_CLASS: + case OP_NCLASS: +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: +#endif + compile_iterator_fallbackpath(common, current); + break; + + case OP_REF: + case OP_REFI: + compile_ref_iterator_fallbackpath(common, current); + break; + + case OP_RECURSE: + compile_recurse_fallbackpath(common, current); + break; + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + compile_assert_fallbackpath(common, current); + break; + + case OP_ONCE: + case OP_ONCE_NC: + case OP_BRA: + case OP_CBRA: + case OP_COND: + case OP_SBRA: + case OP_SCBRA: + case OP_SCOND: + compile_bracket_fallbackpath(common, current); + break; + + case OP_BRAZERO: + if (current->cc[1] > OP_ASSERTBACK_NOT) + compile_bracket_fallbackpath(common, current); + else + compile_assert_fallbackpath(common, current); + break; + + case OP_BRAPOS: + case OP_CBRAPOS: + case OP_SBRAPOS: + case OP_SCBRAPOS: + case OP_BRAPOSZERO: + compile_bracketpos_fallbackpath(common, current); + break; + + case OP_BRAMINZERO: + compile_braminzero_fallbackpath(common, current); + break; + + case OP_FAIL: + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + set_jumps(current->topfallbacks, LABEL()); + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } + current = current->prev; + } +} + +static SLJIT_INLINE void compile_recurse(compiler_common *common) +{ +DEFINE_COMPILER; +pcre_uchar *cc = common->start + common->currententry->start; +pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); +pcre_uchar *ccend = bracketend(cc); +int localsize = get_localsize(common, ccbegin, ccend); +int framesize = get_framesize(common, cc, TRUE); +int alternativesize; +BOOL needsframe; +fallback_common altfallback; +struct sljit_jump *jump; + +SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS); +needsframe = framesize >= 0; +if (!needsframe) + framesize = 0; +alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0; + +SLJIT_ASSERT(common->currententry->entry == NULL); +common->currententry->entry = LABEL(); +set_jumps(common->currententry->calls, common->currententry->entry); + +sljit_emit_fast_enter(compiler, TMP2, 0, 1, 5, 5, common->localsize); +allocate_stack(common, localsize + framesize + alternativesize); +OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0); +copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, STACK_TOP, 0); +if (needsframe) + init_frame(common, cc, framesize + alternativesize - 1, alternativesize, FALSE); + +if (alternativesize > 0) + OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); + +memset(&altfallback, 0, sizeof(fallback_common)); +common->acceptlabel = NULL; +common->accept = NULL; +altfallback.cc = ccbegin; +cc += GET(cc, 1); +while (1) + { + altfallback.top = NULL; + altfallback.topfallbacks = NULL; + + if (altfallback.cc != ccbegin) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); + + compile_hotpath(common, altfallback.cc, cc, &altfallback); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return; + + add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); + + compile_fallbackpath(common, altfallback.top); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + return; + set_jumps(altfallback.topfallbacks, LABEL()); + + if (*cc != OP_ALT) + break; + + altfallback.cc = cc + 1 + LINK_SIZE; + cc += GET(cc, 1); + } +/* None of them matched. */ +OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); +jump = JUMP(SLJIT_JUMP); + +set_jumps(common->accept, LABEL()); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD); +if (needsframe) + { + OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w)); + add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); + OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + alternativesize) * sizeof(sljit_w)); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP3, 0); + } +OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1); + +JUMPHERE(jump); +copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize); +free_stack(common, localsize + framesize + alternativesize); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w)); +OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, TMP2, 0); +sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0); +} + +#undef COMPILE_FALLBACKPATH +#undef CURRENT_AS + +void +PRIV(jit_compile)(const REAL_PCRE *re, PUBL(extra) *extra) +{ +struct sljit_compiler *compiler; +fallback_common rootfallback; +compiler_common common_data; +compiler_common *common = &common_data; +const pcre_uint8 *tables = re->tables; +pcre_study_data *study; +pcre_uchar *ccend; +executable_function *function; +void *executable_func; +sljit_uw executable_size; +struct sljit_label *leave; +struct sljit_label *mainloop = NULL; +struct sljit_label *empty_match_found; +struct sljit_label *empty_match_fallback; +struct sljit_jump *alloc_error; +struct sljit_jump *reqbyte_notfound = NULL; +struct sljit_jump *empty_match; + +SLJIT_ASSERT((extra->flags & PCRE_EXTRA_STUDY_DATA) != 0); +study = extra->study_data; + +if (!tables) + tables = PRIV(default_tables); + +memset(&rootfallback, 0, sizeof(fallback_common)); +rootfallback.cc = (pcre_uchar *)re + re->name_table_offset + re->name_count * re->name_entry_size; + +common->compiler = NULL; +common->start = rootfallback.cc; +common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w); +common->fcc = tables + fcc_offset; +common->lcc = (sljit_w)(tables + lcc_offset); +common->nltype = NLTYPE_FIXED; +switch(re->options & PCRE_NEWLINE_BITS) + { + case 0: + /* Compile-time default */ + switch (NEWLINE) + { + case -1: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; + case -2: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; + default: common->newline = NEWLINE; break; + } + break; + case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break; + case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break; + case PCRE_NEWLINE_CR+ + PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break; + case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break; + case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break; + default: return; + } +if ((re->options & PCRE_BSR_ANYCRLF) != 0) + common->bsr_nltype = NLTYPE_ANYCRLF; +else if ((re->options & PCRE_BSR_UNICODE) != 0) + common->bsr_nltype = NLTYPE_ANY; +else + { +#ifdef BSR_ANYCRLF + common->bsr_nltype = NLTYPE_ANYCRLF; +#else + common->bsr_nltype = NLTYPE_ANY; +#endif + } +common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0; +common->ctypes = (sljit_w)(tables + ctypes_offset); +common->name_table = (sljit_w)((pcre_uchar *)re + re->name_table_offset); +common->name_count = re->name_count; +common->name_entry_size = re->name_entry_size; +common->acceptlabel = NULL; +common->stubs = NULL; +common->entries = NULL; +common->currententry = NULL; +common->accept = NULL; +common->calllimit = NULL; +common->stackalloc = NULL; +common->revertframes = NULL; +common->wordboundary = NULL; +common->anynewline = NULL; +common->hspace = NULL; +common->vspace = NULL; +common->casefulcmp = NULL; +common->caselesscmp = NULL; +common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0; +#ifdef SUPPORT_UTF +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +common->utf = (re->options & PCRE_UTF8) != 0; +#ifdef SUPPORT_UCP +common->use_ucp = (re->options & PCRE_UCP) != 0; +#endif +common->utfreadchar = NULL; +#ifdef COMPILE_PCRE8 +common->utfreadtype8 = NULL; +#endif +#endif /* SUPPORT_UTF */ +#ifdef SUPPORT_UCP +common->getucd = NULL; +#endif +ccend = bracketend(rootfallback.cc); +SLJIT_ASSERT(*rootfallback.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET); +common->localsize = get_localspace(common, rootfallback.cc, ccend); +if (common->localsize < 0) + return; +common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w); +if (common->localsize > SLJIT_MAX_LOCAL_SIZE) + return; +common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int)); +if (!common->localptrs) + return; +memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int)); +set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend); + +compiler = sljit_create_compiler(); +if (!compiler) + { + SLJIT_FREE(common->localptrs); + return; + } +common->compiler = compiler; + +/* Main pcre_jit_exec entry. */ +sljit_emit_enter(compiler, 1, 5, 5, common->localsize); + +/* Register init. */ +reset_ovector(common, (re->top_bracket + 1) * 2); +if ((re->flags & PCRE_REQCHSET) != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, SLJIT_TEMPORARY_REG1, 0); + +OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_SAVED_REG1, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_SAVED_REG1, 0); +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); +OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end)); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); +OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, calllimit)); +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)); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT, TMP1, 0); + +/* Main part of the matching */ +if ((re->options & PCRE_ANCHORED) == 0) + { + mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0); + /* Forward search if possible. */ + if ((re->flags & PCRE_FIRSTSET) != 0) + fast_forward_first_char(common, re->first_char, (re->flags & PCRE_FCH_CASELESS) != 0, (re->options & PCRE_FIRSTLINE) != 0); + else if ((re->flags & PCRE_STARTLINE) != 0) + fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0); + else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0) + fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0); + } +if ((re->flags & PCRE_REQCHSET) != 0) + reqbyte_notfound = search_requested_char(common, re->req_char, (re->flags & PCRE_RCH_CASELESS) != 0, (re->flags & PCRE_FIRSTSET) != 0); + +/* Store the current STR_PTR in OVECTOR(0). */ +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0); +/* Copy the limit of allowed recursions. */ +OP1(SLJIT_MOV, CALL_COUNT, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CALL_LIMIT); + +compile_hotpath(common, rootfallback.cc, ccend, &rootfallback); +if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + sljit_free_compiler(compiler); + SLJIT_FREE(common->localptrs); + return; + } + +empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); +empty_match_found = LABEL(); + +common->acceptlabel = LABEL(); +if (common->accept != NULL) + set_jumps(common->accept, common->acceptlabel); + +/* This means we have a match. Update the ovector. */ +copy_ovector(common, re->top_bracket + 1); +leave = LABEL(); +sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); + +empty_match_fallback = LABEL(); +compile_fallbackpath(common, rootfallback.top); +if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + sljit_free_compiler(compiler); + SLJIT_FREE(common->localptrs); + return; + } + +SLJIT_ASSERT(rootfallback.prev == NULL); + +/* Check we have remaining characters. */ +OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); + +if ((re->options & PCRE_ANCHORED) == 0) + { + if ((re->options & PCRE_FIRSTLINE) == 0) + { + if (study != NULL && study->minlength > 1) + { + OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); + CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop); + } + else + CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop); + } + else + { + if (study != NULL && study->minlength > 1) + { + OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(study->minlength)); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0); + COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END); + COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL); + JUMPTO(SLJIT_C_ZERO, mainloop); + } + else + CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, mainloop); + } + } + +if (reqbyte_notfound != NULL) + JUMPHERE(reqbyte_notfound); +/* Copy OVECTOR(1) to OVECTOR(0) */ +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); +OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH); +JUMPTO(SLJIT_JUMP, leave); + +flush_stubs(common); + +JUMPHERE(empty_match); +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); +CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_fallback); +OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); +CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); +CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found); +JUMPTO(SLJIT_JUMP, empty_match_fallback); + +common->currententry = common->entries; +while (common->currententry != NULL) + { + /* Might add new entries. */ + compile_recurse(common); + if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) + { + sljit_free_compiler(compiler); + SLJIT_FREE(common->localptrs); + return; + } + flush_stubs(common); + common->currententry = common->currententry->next; + } + +/* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */ +/* This is a (really) rare case. */ +set_jumps(common->stackalloc, LABEL()); +/* RETURN_ADDR is not a saved register. */ +sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize); +OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0); +OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE); + +sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize)); +alloc_error = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); +OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); +OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top)); +OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit)); +OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); +sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); + +/* Allocation failed. */ +JUMPHERE(alloc_error); +/* We break the return address cache here, but this is a really rare case. */ +OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_JIT_STACKLIMIT); +JUMPTO(SLJIT_JUMP, leave); + +/* Call limit reached. */ +set_jumps(common->calllimit, LABEL()); +OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_MATCHLIMIT); +JUMPTO(SLJIT_JUMP, leave); + +if (common->revertframes != NULL) + { + set_jumps(common->revertframes, LABEL()); + do_revertframes(common); + } +if (common->wordboundary != NULL) + { + set_jumps(common->wordboundary, LABEL()); + check_wordboundary(common); + } +if (common->anynewline != NULL) + { + set_jumps(common->anynewline, LABEL()); + check_anynewline(common); + } +if (common->hspace != NULL) + { + set_jumps(common->hspace, LABEL()); + check_hspace(common); + } +if (common->vspace != NULL) + { + set_jumps(common->vspace, LABEL()); + check_vspace(common); + } +if (common->casefulcmp != NULL) + { + set_jumps(common->casefulcmp, LABEL()); + do_casefulcmp(common); + } +if (common->caselesscmp != NULL) + { + set_jumps(common->caselesscmp, LABEL()); + do_caselesscmp(common); + } +#ifdef SUPPORT_UTF +if (common->utfreadchar != NULL) + { + set_jumps(common->utfreadchar, LABEL()); + do_utfreadchar(common); + } +#ifdef COMPILE_PCRE8 +if (common->utfreadtype8 != NULL) + { + set_jumps(common->utfreadtype8, LABEL()); + do_utfreadtype8(common); + } +#endif +#endif /* COMPILE_PCRE8 */ +#ifdef SUPPORT_UCP +if (common->getucd != NULL) + { + set_jumps(common->getucd, LABEL()); + do_getucd(common); + } +#endif + +SLJIT_FREE(common->localptrs); +executable_func = sljit_generate_code(compiler); +executable_size = sljit_get_generated_code_size(compiler); +sljit_free_compiler(compiler); +if (executable_func == NULL) + return; + +function = SLJIT_MALLOC(sizeof(executable_function)); +if (function == NULL) + { + /* This case is highly unlikely since we just recently + freed a lot of memory. Although not impossible. */ + sljit_free_code(executable_func); + return; + } + +function->executable_func = executable_func; +function->executable_size = executable_size; +function->callback = NULL; +function->userdata = NULL; +extra->executable_jit = function; +extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT; +} + +static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function) +{ +union { + void* executable_func; + jit_function call_executable_func; +} convert_executable_func; +pcre_uint8 local_area[LOCAL_SPACE_SIZE]; +struct sljit_stack local_stack; + +local_stack.top = (sljit_w)&local_area; +local_stack.base = local_stack.top; +local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE; +local_stack.max_limit = local_stack.limit; +arguments->stack = &local_stack; +convert_executable_func.executable_func = function->executable_func; +return convert_executable_func.call_executable_func(arguments); +} + +int +PRIV(jit_exec)(const REAL_PCRE *re, void *executable_func, + const pcre_uchar *subject, int length, int start_offset, int options, + int match_limit, int *offsets, int offsetcount) +{ +executable_function *function = (executable_function*)executable_func; +union { + void* executable_func; + jit_function call_executable_func; +} convert_executable_func; +jit_arguments arguments; +int maxoffsetcount; +int retval; + +/* Sanity checks should be handled by pcre_exec. */ +arguments.stack = NULL; +arguments.str = subject + start_offset; +arguments.begin = subject; +arguments.end = subject + length; +arguments.calllimit = match_limit; /* JIT decreases this value less times. */ +arguments.notbol = (options & PCRE_NOTBOL) != 0; +arguments.noteol = (options & PCRE_NOTEOL) != 0; +arguments.notempty = (options & PCRE_NOTEMPTY) != 0; +arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0; +arguments.offsets = offsets; + +/* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of +the output vector for storing captured strings, with the remainder used as +workspace. We don't need the workspace here. For compatibility, we limit the +number of captured strings in the same way as pcre_exec(), so that the user +gets the same result with and without JIT. */ + +if (offsetcount != 2) + offsetcount = ((offsetcount - (offsetcount % 3)) * 2) / 3; +maxoffsetcount = (re->top_bracket + 1) * 2; +if (offsetcount > maxoffsetcount) + offsetcount = maxoffsetcount; +arguments.offsetcount = offsetcount; + +if (function->callback) + arguments.stack = (struct sljit_stack*)function->callback(function->userdata); +else + arguments.stack = (struct sljit_stack*)function->userdata; + +if (arguments.stack == NULL) + retval = jit_machine_stack_exec(&arguments, function); +else + { + convert_executable_func.executable_func = function->executable_func; + retval = convert_executable_func.call_executable_func(&arguments); + } + +if (retval * 2 > offsetcount) + retval = 0; +return retval; +} + +void +PRIV(jit_free)(void *executable_func) +{ +executable_function *function = (executable_function*)executable_func; +sljit_free_code(function->executable_func); +SLJIT_FREE(function); +} + +int +PRIV(jit_get_size)(void *executable_func) +{ +return ((executable_function*)executable_func)->executable_size; +} + +const char* +PRIV(jit_get_target)(void) +{ +return sljit_get_platform_name(); +} + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL pcre_jit_stack * +pcre_jit_stack_alloc(int startsize, int maxsize) +#else +PCRE_EXP_DECL pcre16_jit_stack * +pcre16_jit_stack_alloc(int startsize, int maxsize) +#endif +{ +if (startsize < 1 || maxsize < 1) + return NULL; +if (startsize > maxsize) + startsize = maxsize; +startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); +maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); +return (PUBL(jit_stack)*)sljit_allocate_stack(startsize, maxsize); +} + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL void +pcre_jit_stack_free(pcre_jit_stack *stack) +#else +PCRE_EXP_DECL void +pcre16_jit_stack_free(pcre16_jit_stack *stack) +#endif +{ +sljit_free_stack((struct sljit_stack*)stack); +} + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL void +pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) +#else +PCRE_EXP_DECL void +pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) +#endif +{ +executable_function *function; +if (extra != NULL && + (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && + extra->executable_jit != NULL) + { + function = (executable_function*)extra->executable_jit; + function->callback = callback; + function->userdata = userdata; + } +} + +#else /* SUPPORT_JIT */ + +/* These are dummy functions to avoid linking errors when JIT support is not +being compiled. */ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL pcre_jit_stack * +pcre_jit_stack_alloc(int startsize, int maxsize) +#else +PCRE_EXP_DECL pcre16_jit_stack * +pcre16_jit_stack_alloc(int startsize, int maxsize) +#endif +{ +(void)startsize; +(void)maxsize; +return NULL; +} + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL void +pcre_jit_stack_free(pcre_jit_stack *stack) +#else +PCRE_EXP_DECL void +pcre16_jit_stack_free(pcre16_jit_stack *stack) +#endif +{ +(void)stack; +} + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DECL void +pcre_assign_jit_stack(pcre_extra *extra, pcre_jit_callback callback, void *userdata) +#else +PCRE_EXP_DECL void +pcre16_assign_jit_stack(pcre16_extra *extra, pcre16_jit_callback callback, void *userdata) +#endif +{ +(void)extra; +(void)callback; +(void)userdata; +} + +#endif + +/* End of pcre_jit_compile.c */ diff --git a/src/3rdparty/pcre/pcre_maketables.c b/src/3rdparty/pcre/pcre_maketables.c new file mode 100644 index 0000000000..caacdba3e6 --- /dev/null +++ b/src/3rdparty/pcre/pcre_maketables.c @@ -0,0 +1,148 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_maketables(), which builds +character tables for PCRE in the current locale. The file is compiled on its +own as part of the PCRE library. However, it is also included in the +compilation of dftables.c, in which case the macro DFTABLES is defined. */ + + +#ifndef DFTABLES +# ifdef PCRE_HAVE_CONFIG_H +# include "config.h" +# endif +# include "pcre_internal.h" +#endif + + +/************************************************* +* Create PCRE character tables * +*************************************************/ + +/* This function builds a set of character tables for use by PCRE and returns +a pointer to them. They are build using the ctype functions, and consequently +their contents will depend upon the current locale setting. When compiled as +part of the library, the store is obtained via PUBL(malloc)(), but when +compiled inside dftables, use malloc(). + +Arguments: none +Returns: pointer to the contiguous block of data +*/ + +#ifdef COMPILE_PCRE8 +const unsigned char * +pcre_maketables(void) +#else +const unsigned char * +pcre16_maketables(void) +#endif +{ +unsigned char *yield, *p; +int i; + +#ifndef DFTABLES +yield = (unsigned char*)(PUBL(malloc))(tables_length); +#else +yield = (unsigned char*)malloc(tables_length); +#endif + +if (yield == NULL) return NULL; +p = yield; + +/* First comes the lower casing table */ + +for (i = 0; i < 256; i++) *p++ = tolower(i); + +/* Next the case-flipping table */ + +for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i); + +/* Then the character class tables. Don't try to be clever and save effort on +exclusive ones - in some locales things may be different. Note that the table +for "space" includes everything "isspace" gives, including VT in the default +locale. This makes it work for the POSIX class [:space:]. Note also that it is +possible for a character to be alnum or alpha without being lower or upper, +such as "male and female ordinals" (\xAA and \xBA) in the fr_FR locale (at +least under Debian Linux's locales as of 12/2005). So we must test for alnum +specially. */ + +memset(p, 0, cbit_length); +for (i = 0; i < 256; i++) + { + if (isdigit(i)) p[cbit_digit + i/8] |= 1 << (i&7); + if (isupper(i)) p[cbit_upper + i/8] |= 1 << (i&7); + if (islower(i)) p[cbit_lower + i/8] |= 1 << (i&7); + if (isalnum(i)) p[cbit_word + i/8] |= 1 << (i&7); + if (i == '_') p[cbit_word + i/8] |= 1 << (i&7); + if (isspace(i)) p[cbit_space + i/8] |= 1 << (i&7); + if (isxdigit(i))p[cbit_xdigit + i/8] |= 1 << (i&7); + if (isgraph(i)) p[cbit_graph + i/8] |= 1 << (i&7); + if (isprint(i)) p[cbit_print + i/8] |= 1 << (i&7); + if (ispunct(i)) p[cbit_punct + i/8] |= 1 << (i&7); + if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1 << (i&7); + } +p += cbit_length; + +/* Finally, the character type table. In this, we exclude VT from the white +space chars, because Perl doesn't recognize it as such for \s and for comments +within regexes. */ + +for (i = 0; i < 256; i++) + { + int x = 0; + if (i != 0x0b && isspace(i)) x += ctype_space; + if (isalpha(i)) x += ctype_letter; + if (isdigit(i)) x += ctype_digit; + if (isxdigit(i)) x += ctype_xdigit; + if (isalnum(i) || i == '_') x += ctype_word; + + /* Note: strchr includes the terminating zero in the characters it considers. + In this instance, that is ok because we want binary zero to be flagged as a + meta-character, which in this sense is any character that terminates a run + of data characters. */ + + if (strchr("\\*+?{^.$|()[", i) != 0) x += ctype_meta; + *p++ = x; + } + +return yield; +} + +/* End of pcre_maketables.c */ diff --git a/src/3rdparty/pcre/pcre_newline.c b/src/3rdparty/pcre/pcre_newline.c new file mode 100644 index 0000000000..8ee2a6e588 --- /dev/null +++ b/src/3rdparty/pcre/pcre_newline.c @@ -0,0 +1,184 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains internal functions for testing newlines when more than +one kind of newline is to be recognized. When a newline is found, its length is +returned. In principle, we could implement several newline "types", each +referring to a different set of newline characters. At present, PCRE supports +only NLTYPE_FIXED, which gets handled without these functions, NLTYPE_ANYCRLF, +and NLTYPE_ANY. The full list of Unicode newline characters is taken from +http://unicode.org/unicode/reports/tr18/. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + + +/************************************************* +* Check for newline at given position * +*************************************************/ + +/* It is guaranteed that the initial value of ptr is less than the end of the +string that is being processed. + +Arguments: + ptr pointer to possible newline + type the newline type + endptr pointer to the end of the string + lenptr where to return the length + utf TRUE if in utf mode + +Returns: TRUE or FALSE +*/ + +BOOL +PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr, + BOOL utf) +{ +int c; +(void)utf; +#ifdef SUPPORT_UTF +if (utf) + { + GETCHAR(c, ptr); + } +else +#endif /* SUPPORT_UTF */ + c = *ptr; + +if (type == NLTYPE_ANYCRLF) switch(c) + { + case 0x000a: *lenptr = 1; return TRUE; /* LF */ + case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1; + return TRUE; /* CR */ + default: return FALSE; + } + +/* NLTYPE_ANY */ + +else switch(c) + { + case 0x000a: /* LF */ + case 0x000b: /* VT */ + case 0x000c: *lenptr = 1; return TRUE; /* FF */ + case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1; + return TRUE; /* CR */ +#ifdef COMPILE_PCRE8 + case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 3; return TRUE; /* PS */ +#else + case 0x0085: /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 1; return TRUE; /* PS */ +#endif /* COMPILE_PCRE8 */ + default: return FALSE; + } +} + + + +/************************************************* +* Check for newline at previous position * +*************************************************/ + +/* It is guaranteed that the initial value of ptr is greater than the start of +the string that is being processed. + +Arguments: + ptr pointer to possible newline + type the newline type + startptr pointer to the start of the string + lenptr where to return the length + utf TRUE if in utf mode + +Returns: TRUE or FALSE +*/ + +BOOL +PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr, + BOOL utf) +{ +int c; +(void)utf; +ptr--; +#ifdef SUPPORT_UTF +if (utf) + { + BACKCHAR(ptr); + GETCHAR(c, ptr); + } +else +#endif /* SUPPORT_UTF */ + c = *ptr; + +if (type == NLTYPE_ANYCRLF) switch(c) + { + case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; + return TRUE; /* LF */ + case 0x000d: *lenptr = 1; return TRUE; /* CR */ + default: return FALSE; + } + +else switch(c) + { + case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1; + return TRUE; /* LF */ + case 0x000b: /* VT */ + case 0x000c: /* FF */ + case 0x000d: *lenptr = 1; return TRUE; /* CR */ +#ifdef COMPILE_PCRE8 + case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 3; return TRUE; /* PS */ +#else + case 0x0085: /* NEL */ + case 0x2028: /* LS */ + case 0x2029: *lenptr = 1; return TRUE; /* PS */ +#endif /* COMPILE_PCRE8 */ + default: return FALSE; + } +} + +/* End of pcre_newline.c */ diff --git a/src/3rdparty/pcre/pcre_ord2utf8.c b/src/3rdparty/pcre/pcre_ord2utf8.c new file mode 100644 index 0000000000..6afd235f79 --- /dev/null +++ b/src/3rdparty/pcre/pcre_ord2utf8.c @@ -0,0 +1,97 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This file contains a private PCRE function that converts an ordinal +character value into a UTF8 string. */ + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Convert character value to UTF-8 * +*************************************************/ + +/* This function takes an integer value in the range 0 - 0x10ffff +and encodes it as a UTF-8 character in 1 to 6 pcre_uchars. + +Arguments: + cvalue the character value + buffer pointer to buffer for result - at least 6 pcre_uchars long + +Returns: number of characters placed in the buffer +*/ + +int +PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer) +{ +#ifdef SUPPORT_UTF + +register int i, j; + +/* Checking invalid cvalue character, encoded as invalid UTF-16 character. +Should never happen in practice. */ +if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000) + cvalue = 0xfffe; + +for (i = 0; i < PRIV(utf8_table1_size); i++) + if ((int)cvalue <= PRIV(utf8_table1)[i]) break; +buffer += i; +for (j = i; j > 0; j--) + { + *buffer-- = 0x80 | (cvalue & 0x3f); + cvalue >>= 6; + } +*buffer = PRIV(utf8_table2)[i] | cvalue; +return i + 1; + +#else + +(void)(cvalue); /* Keep compiler happy; this function won't ever be */ +(void)(buffer); /* called when SUPPORT_UTF is not defined. */ +return 0; + +#endif +} + +/* End of pcre_ord2utf8.c */ diff --git a/src/3rdparty/pcre/pcre_refcount.c b/src/3rdparty/pcre/pcre_refcount.c new file mode 100644 index 0000000000..263a1e11dc --- /dev/null +++ b/src/3rdparty/pcre/pcre_refcount.c @@ -0,0 +1,89 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_refcount(), which is an +auxiliary function that can be used to maintain a reference count in a compiled +pattern data block. This might be helpful in applications where the block is +shared by different users. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Maintain reference count * +*************************************************/ + +/* The reference count is a 16-bit field, initialized to zero. It is not +possible to transfer a non-zero count from one host to a different host that +has a different byte order - though I can't see why anyone in their right mind +would ever want to do that! + +Arguments: + argument_re points to compiled code + adjust value to add to the count + +Returns: the (possibly updated) count value (a non-negative number), or + a negative error number +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre_refcount(pcre *argument_re, int adjust) +#else +PCRE_EXP_DEFN int PCRE_CALL_CONVENTION +pcre16_refcount(pcre16 *argument_re, int adjust) +#endif +{ +REAL_PCRE *re = (REAL_PCRE *)argument_re; +if (re == NULL) return PCRE_ERROR_NULL; +if (re->magic_number != MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC; +if ((re->flags & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE; +re->ref_count = (-adjust > re->ref_count)? 0 : + (adjust + re->ref_count > 65535)? 65535 : + re->ref_count + adjust; +return re->ref_count; +} + +/* End of pcre_refcount.c */ diff --git a/src/3rdparty/pcre/pcre_string_utils.c b/src/3rdparty/pcre/pcre_string_utils.c new file mode 100644 index 0000000000..d4545532a7 --- /dev/null +++ b/src/3rdparty/pcre/pcre_string_utils.c @@ -0,0 +1,168 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that is used to match an extended +class. It is used by both pcre_exec() and pcre_def_exec(). */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#ifndef COMPILE_PCRE8 + +/************************************************* +* Compare string utilities * +*************************************************/ + +/* The following two functions compares two strings. Basically an strcmp +for non 8 bit characters. + +Arguments: + str1 first string + str2 second string + +Returns: 0 if both string are equal (like strcmp), 1 otherwise +*/ + +int +PRIV(strcmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2) +{ +pcre_uchar c1; +pcre_uchar c2; + +while (*str1 != '\0' || *str2 != '\0') + { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) + return ((c1 > c2) << 1) - 1; + } +/* Both length and characters must be equal. */ +return 0; +} + +int +PRIV(strcmp_uc_c8)(const pcre_uchar *str1, const char *str2) +{ +const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; +pcre_uchar c1; +pcre_uchar c2; + +while (*str1 != '\0' || *ustr2 != '\0') + { + c1 = *str1++; + c2 = (pcre_uchar)*ustr2++; + if (c1 != c2) + return ((c1 > c2) << 1) - 1; + } +/* Both length and characters must be equal. */ +return 0; +} + +/* The following two functions compares two, fixed length +strings. Basically an strncmp for non 8 bit characters. + +Arguments: + str1 first string + str2 second string + num size of the string + +Returns: 0 if both string are equal (like strcmp), 1 otherwise +*/ + +int +PRIV(strncmp_uc_uc)(const pcre_uchar *str1, const pcre_uchar *str2, unsigned int num) +{ +pcre_uchar c1; +pcre_uchar c2; + +while (num-- > 0) + { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) + return ((c1 > c2) << 1) - 1; + } +/* Both length and characters must be equal. */ +return 0; +} + +int +PRIV(strncmp_uc_c8)(const pcre_uchar *str1, const char *str2, unsigned int num) +{ +const pcre_uint8 *ustr2 = (pcre_uint8 *)str2; +pcre_uchar c1; +pcre_uchar c2; + +while (num-- > 0) + { + c1 = *str1++; + c2 = (pcre_uchar)*ustr2++; + if (c1 != c2) + return ((c1 > c2) << 1) - 1; + } +/* Both length and characters must be equal. */ +return 0; +} + +/* The following function returns with the length of +a zero terminated string. Basically an strlen for non 8 bit characters. + +Arguments: + str string + +Returns: length of the string +*/ + +unsigned int +PRIV(strlen_uc)(const pcre_uchar *str) +{ +unsigned int len = 0; +while (*str++ != 0) + len++; +return len; +} + +#endif /* COMPILE_PCRE8 */ + +/* End of pcre_string_utils.c */ diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c new file mode 100644 index 0000000000..6b6edc3f31 --- /dev/null +++ b/src/3rdparty/pcre/pcre_study.c @@ -0,0 +1,1527 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_study(), along with local +supporting functions. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#define SET_BIT(c) start_bits[c/8] |= (1 << (c&7)) + +/* Returns from set_start_bits() */ + +enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN }; + + + +/************************************************* +* Find the minimum subject length for a group * +*************************************************/ + +/* Scan a parenthesized group and compute the minimum length of subject that +is needed to match it. This is a lower bound; it does not mean there is a +string of that length that matches. In UTF8 mode, the result is in characters +rather than bytes. + +Arguments: + code pointer to start of group (the bracket) + startcode pointer to start of the whole pattern + options the compiling options + int RECURSE depth + +Returns: the minimum length + -1 if \C in UTF-8 mode or (*ACCEPT) was encountered + -2 internal error (missing capturing bracket) + -3 internal error (opcode not listed) +*/ + +static int +find_minlength(const pcre_uchar *code, const pcre_uchar *startcode, int options, + int recurse_depth) +{ +int length = -1; +/* PCRE_UTF16 has the same value as PCRE_UTF8. */ +BOOL utf = (options & PCRE_UTF8) != 0; +BOOL had_recurse = FALSE; +register int branchlength = 0; +register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; + +if (*code == OP_CBRA || *code == OP_SCBRA || + *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; + +/* Scan along the opcodes for this branch. If we get to the end of the +branch, check the length against that of the other branches. */ + +for (;;) + { + int d, min; + pcre_uchar *cs, *ce; + register int op = *cc; + + switch (op) + { + case OP_COND: + case OP_SCOND: + + /* If there is only one branch in a condition, the implied branch has zero + length, so we don't add anything. This covers the DEFINE "condition" + automatically. */ + + cs = cc + GET(cc, 1); + if (*cs != OP_ALT) + { + cc = cs + 1 + LINK_SIZE; + break; + } + + /* Otherwise we can fall through and treat it the same as any other + subpattern. */ + + case OP_CBRA: + case OP_SCBRA: + case OP_BRA: + case OP_SBRA: + case OP_CBRAPOS: + case OP_SCBRAPOS: + case OP_BRAPOS: + case OP_SBRAPOS: + case OP_ONCE: + case OP_ONCE_NC: + d = find_minlength(cc, startcode, options, recurse_depth); + if (d < 0) return d; + branchlength += d; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* ACCEPT makes things far too complicated; we have to give up. */ + + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + return -1; + + /* Reached end of a branch; if it's a ket it is the end of a nested + call. If it's ALT it is an alternation in a nested call. If it is END it's + the end of the outer call. All can be handled by the same code. If an + ACCEPT was previously encountered, use the length that was in force at that + time, and pass back the shortest ACCEPT length. */ + + case OP_ALT: + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_KETRPOS: + case OP_END: + if (length < 0 || (!had_recurse && branchlength < length)) + length = branchlength; + if (op != OP_ALT) return length; + cc += 1 + LINK_SIZE; + branchlength = 0; + had_recurse = FALSE; + break; + + /* Skip over assertive subpatterns */ + + case OP_ASSERT: + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do cc += GET(cc, 1); while (*cc == OP_ALT); + /* Fall through */ + + /* Skip over things that don't match chars */ + + case OP_REVERSE: + case OP_CREF: + case OP_NCREF: + case OP_RREF: + case OP_NRREF: + case OP_DEF: + case OP_CALLOUT: + case OP_SOD: + case OP_SOM: + case OP_EOD: + case OP_EODN: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + cc += PRIV(OP_lengths)[*cc]; + break; + + /* Skip over a subpattern that has a {0} or {0,x} quantifier */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + case OP_SKIPZERO: + cc += PRIV(OP_lengths)[*cc]; + do cc += GET(cc, 1); while (*cc == OP_ALT); + cc += 1 + LINK_SIZE; + break; + + /* Handle literal characters and + repetitions */ + + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + case OP_PLUS: + case OP_PLUSI: + case OP_MINPLUS: + case OP_MINPLUSI: + case OP_POSPLUS: + case OP_POSPLUSI: + case OP_NOTPLUS: + case OP_NOTPLUSI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: + branchlength++; + cc += 2; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSPLUS: + branchlength++; + cc += (cc[1] == OP_PROP || cc[1] == OP_NOTPROP)? 4 : 2; + break; + + /* Handle exact repetitions. The count is already in characters, but we + need to skip over a multibyte character in UTF8 mode. */ + + case OP_EXACT: + case OP_EXACTI: + case OP_NOTEXACT: + case OP_NOTEXACTI: + branchlength += GET2(cc,1); + cc += 2 + IMM2_SIZE; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; + + case OP_TYPEEXACT: + branchlength += GET2(cc,1); + cc += 2 + IMM2_SIZE + ((cc[1 + IMM2_SIZE] == OP_PROP + || cc[1 + IMM2_SIZE] == OP_NOTPROP)? 2 : 0); + break; + + /* Handle single-char non-literal matchers */ + + case OP_PROP: + case OP_NOTPROP: + cc += 2; + /* Fall through */ + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + case OP_EXTUNI: + case OP_HSPACE: + case OP_NOT_HSPACE: + case OP_VSPACE: + case OP_NOT_VSPACE: + branchlength++; + cc++; + break; + + /* "Any newline" might match two characters, but it also might match just + one. */ + + case OP_ANYNL: + branchlength += 1; + cc++; + break; + + /* The single-byte matcher means we can't proceed in UTF-8 mode. (In + non-UTF-8 mode \C will actually be turned into OP_ALLANY, so won't ever + appear, but leave the code, just in case.) */ + + case OP_ANYBYTE: +#ifdef SUPPORT_UTF + if (utf) return -1; +#endif + branchlength++; + cc++; + break; + + /* For repeated character types, we have to test for \p and \P, which have + an extra two bytes of parameters. */ + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSQUERY: + if (cc[1] == OP_PROP || cc[1] == OP_NOTPROP) cc += 2; + cc += PRIV(OP_lengths)[op]; + break; + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + if (cc[1 + IMM2_SIZE] == OP_PROP + || cc[1 + IMM2_SIZE] == OP_NOTPROP) cc += 2; + cc += PRIV(OP_lengths)[op]; + break; + + /* Check a class for variable quantification */ + +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: + cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS]; + /* Fall through */ +#endif + + case OP_CLASS: + case OP_NCLASS: + cc += PRIV(OP_lengths)[OP_CLASS]; + + switch (*cc) + { + case OP_CRPLUS: + case OP_CRMINPLUS: + branchlength++; + /* Fall through */ + + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + cc++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + branchlength += GET2(cc,1); + cc += 1 + 2 * IMM2_SIZE; + break; + + default: + branchlength++; + break; + } + break; + + /* Backreferences and subroutine calls are treated in the same way: we find + the minimum length for the subpattern. A recursion, however, causes an + a flag to be set that causes the length of this branch to be ignored. The + logic is that a recursion can only make sense if there is another + alternation that stops the recursing. That will provide the minimum length + (when no recursion happens). A backreference within the group that it is + referencing behaves in the same way. + + If PCRE_JAVASCRIPT_COMPAT is set, a backreference to an unset bracket + matches an empty string (by default it causes a matching failure), so in + that case we must set the minimum length to zero. */ + + case OP_REF: + case OP_REFI: + if ((options & PCRE_JAVASCRIPT_COMPAT) == 0) + { + ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(cc, 1)); + if (cs == NULL) return -2; + do ce += GET(ce, 1); while (*ce == OP_ALT); + if (cc > cs && cc < ce) + { + d = 0; + had_recurse = TRUE; + } + else + { + d = find_minlength(cs, startcode, options, recurse_depth); + } + } + else d = 0; + cc += 1 + IMM2_SIZE; + + /* Handle repeated back references */ + + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + min = 0; + cc++; + break; + + case OP_CRPLUS: + case OP_CRMINPLUS: + min = 1; + cc++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + min = GET2(cc, 1); + cc += 1 + 2 * IMM2_SIZE; + break; + + default: + min = 1; + break; + } + + branchlength += min * d; + break; + + /* We can easily detect direct recursion, but not mutual recursion. This is + caught by a recursion depth count. */ + + case OP_RECURSE: + cs = ce = (pcre_uchar *)startcode + GET(cc, 1); + do ce += GET(ce, 1); while (*ce == OP_ALT); + if ((cc > cs && cc < ce) || recurse_depth > 10) + had_recurse = TRUE; + else + { + branchlength += find_minlength(cs, startcode, options, recurse_depth + 1); + } + cc += 1 + LINK_SIZE; + break; + + /* Anything else does not or need not match a character. We can get the + item's length from the table, but for those that can match zero occurrences + of a character, we must take special action for UTF-8 characters. As it + happens, the "NOT" versions of these opcodes are used at present only for + ASCII characters, so they could be omitted from this list. However, in + future that may change, so we include them here so as not to leave a + gotcha for a future maintainer. */ + + case OP_UPTO: + case OP_UPTOI: + case OP_NOTUPTO: + case OP_NOTUPTOI: + case OP_MINUPTO: + case OP_MINUPTOI: + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: + case OP_POSUPTO: + case OP_POSUPTOI: + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: + + case OP_STAR: + case OP_STARI: + case OP_NOTSTAR: + case OP_NOTSTARI: + case OP_MINSTAR: + case OP_MINSTARI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: + case OP_POSSTAR: + case OP_POSSTARI: + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: + + case OP_QUERY: + case OP_QUERYI: + case OP_NOTQUERY: + case OP_NOTQUERYI: + case OP_MINQUERY: + case OP_MINQUERYI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: + case OP_POSQUERY: + case OP_POSQUERYI: + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: + + cc += PRIV(OP_lengths)[op]; +#ifdef SUPPORT_UTF + if (utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; + + /* Skip these, but we need to add in the name length. */ + + case OP_MARK: + case OP_PRUNE_ARG: + case OP_SKIP_ARG: + case OP_THEN_ARG: + cc += PRIV(OP_lengths)[op] + cc[1]; + break; + + /* The remaining opcodes are just skipped over. */ + + case OP_CLOSE: + case OP_COMMIT: + case OP_FAIL: + case OP_PRUNE: + case OP_SET_SOM: + case OP_SKIP: + case OP_THEN: + cc += PRIV(OP_lengths)[op]; + break; + + /* This should not occur: we list all opcodes explicitly so that when + new ones get added they are properly considered. */ + + default: + return -3; + } + } +/* Control never gets here */ +} + + + +/************************************************* +* Set a bit and maybe its alternate case * +*************************************************/ + +/* Given a character, set its first byte's bit in the table, and also the +corresponding bit for the other version of a letter if we are caseless. In +UTF-8 mode, for characters greater than 127, we can only do the caseless thing +when Unicode property support is available. + +Arguments: + start_bits points to the bit map + p points to the character + caseless the caseless flag + cd the block with char table pointers + utf TRUE for UTF-8 / UTF-16 mode + +Returns: pointer after the character +*/ + +static const pcre_uchar * +set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless, + compile_data *cd, BOOL utf) +{ +unsigned int c = *p; + +#ifdef COMPILE_PCRE8 +SET_BIT(c); + +#ifdef SUPPORT_UTF +if (utf && c > 127) + { + GETCHARINC(c, p); +#ifdef SUPPORT_UCP + if (caseless) + { + pcre_uchar buff[6]; + c = UCD_OTHERCASE(c); + (void)PRIV(ord2utf)(c, buff); + SET_BIT(buff[0]); + } +#endif + return p; + } +#endif + +/* Not UTF-8 mode, or character is less than 127. */ + +if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); +return p + 1; +#endif + +#ifdef COMPILE_PCRE16 +if (c > 0xff) + { + c = 0xff; + caseless = FALSE; + } +SET_BIT(c); + +#ifdef SUPPORT_UTF +if (utf && c > 127) + { + GETCHARINC(c, p); +#ifdef SUPPORT_UCP + if (caseless) + { + c = UCD_OTHERCASE(c); + if (c > 0xff) + c = 0xff; + SET_BIT(c); + } +#endif + return p; + } +#endif + +if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]); +return p + 1; +#endif +} + + + +/************************************************* +* Set bits for a positive character type * +*************************************************/ + +/* This function sets starting bits for a character type. In UTF-8 mode, we can +only do a direct setting for bytes less than 128, as otherwise there can be +confusion with bytes in the middle of UTF-8 characters. In a "traditional" +environment, the tables will only recognize ASCII characters anyway, but in at +least one Windows environment, some higher bytes bits were set in the tables. +So we deal with that case by considering the UTF-8 encoding. + +Arguments: + start_bits the starting bitmap + cbit type the type of character wanted + table_limit 32 for non-UTF-8; 16 for UTF-8 + cd the block with char table pointers + +Returns: nothing +*/ + +static void +set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit, + compile_data *cd) +{ +register int c; +for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type]; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +if (table_limit == 32) return; +for (c = 128; c < 256; c++) + { + if ((cd->cbits[c/8] & (1 << (c&7))) != 0) + { + pcre_uchar buff[6]; + (void)PRIV(ord2utf)(c, buff); + SET_BIT(buff[0]); + } + } +#endif +} + + +/************************************************* +* Set bits for a negative character type * +*************************************************/ + +/* This function sets starting bits for a negative character type such as \D. +In UTF-8 mode, we can only do a direct setting for bytes less than 128, as +otherwise there can be confusion with bytes in the middle of UTF-8 characters. +Unlike in the positive case, where we can set appropriate starting bits for +specific high-valued UTF-8 characters, in this case we have to set the bits for +all high-valued characters. The lowest is 0xc2, but we overkill by starting at +0xc0 (192) for simplicity. + +Arguments: + start_bits the starting bitmap + cbit type the type of character wanted + table_limit 32 for non-UTF-8; 16 for UTF-8 + cd the block with char table pointers + +Returns: nothing +*/ + +static void +set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit, + compile_data *cd) +{ +register int c; +for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type]; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff; +#endif +} + + + +/************************************************* +* Create bitmap of starting bytes * +*************************************************/ + +/* This function scans a compiled unanchored expression recursively and +attempts to build a bitmap of the set of possible starting bytes. As time goes +by, we may be able to get more clever at doing this. The SSB_CONTINUE return is +useful for parenthesized groups in patterns such as (a*)b where the group +provides some optional starting bytes but scanning must continue at the outer +level to find at least one mandatory byte. At the outermost level, this +function fails unless the result is SSB_DONE. + +Arguments: + code points to an expression + start_bits points to a 32-byte table, initialized to 0 + utf TRUE if in UTF-8 / UTF-16 mode + cd the block with char table pointers + +Returns: SSB_FAIL => Failed to find any starting bytes + SSB_DONE => Found mandatory starting bytes + SSB_CONTINUE => Found optional starting bytes + SSB_UNKNOWN => Hit an unrecognized opcode +*/ + +static int +set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf, + compile_data *cd) +{ +register int c; +int yield = SSB_DONE; +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 +int table_limit = utf? 16:32; +#else +int table_limit = 32; +#endif + +#if 0 +/* ========================================================================= */ +/* The following comment and code was inserted in January 1999. In May 2006, +when it was observed to cause compiler warnings about unused values, I took it +out again. If anybody is still using OS/2, they will have to put it back +manually. */ + +/* This next statement and the later reference to dummy are here in order to +trick the optimizer of the IBM C compiler for OS/2 into generating correct +code. Apparently IBM isn't going to fix the problem, and we would rather not +disable optimization (in this module it actually makes a big difference, and +the pcre module can use all the optimization it can get). */ + +volatile int dummy; +/* ========================================================================= */ +#endif + +do + { + BOOL try_next = TRUE; + const pcre_uchar *tcode = code + 1 + LINK_SIZE; + + if (*code == OP_CBRA || *code == OP_SCBRA || + *code == OP_CBRAPOS || *code == OP_SCBRAPOS) tcode += IMM2_SIZE; + + while (try_next) /* Loop for items in this branch */ + { + int rc; + + switch(*tcode) + { + /* If we reach something we don't understand, it means a new opcode has + been created that hasn't been added to this code. Hopefully this problem + will be discovered during testing. */ + + default: + return SSB_UNKNOWN; + + /* Fail for a valid opcode that implies no starting bits. */ + + case OP_ACCEPT: + case OP_ASSERT_ACCEPT: + case OP_ALLANY: + case OP_ANY: + case OP_ANYBYTE: + case OP_CIRC: + case OP_CIRCM: + case OP_CLOSE: + case OP_COMMIT: + case OP_COND: + case OP_CREF: + case OP_DEF: + case OP_DOLL: + case OP_DOLLM: + case OP_END: + case OP_EOD: + case OP_EODN: + case OP_EXTUNI: + case OP_FAIL: + case OP_MARK: + case OP_NCREF: + case OP_NOT: + case OP_NOTEXACT: + case OP_NOTEXACTI: + case OP_NOTI: + case OP_NOTMINPLUS: + case OP_NOTMINPLUSI: + case OP_NOTMINQUERY: + case OP_NOTMINQUERYI: + case OP_NOTMINSTAR: + case OP_NOTMINSTARI: + case OP_NOTMINUPTO: + case OP_NOTMINUPTOI: + case OP_NOTPLUS: + case OP_NOTPLUSI: + case OP_NOTPOSPLUS: + case OP_NOTPOSPLUSI: + case OP_NOTPOSQUERY: + case OP_NOTPOSQUERYI: + case OP_NOTPOSSTAR: + case OP_NOTPOSSTARI: + case OP_NOTPOSUPTO: + case OP_NOTPOSUPTOI: + case OP_NOTPROP: + case OP_NOTQUERY: + case OP_NOTQUERYI: + case OP_NOTSTAR: + case OP_NOTSTARI: + case OP_NOTUPTO: + case OP_NOTUPTOI: + case OP_NOT_HSPACE: + case OP_NOT_VSPACE: + case OP_NRREF: + case OP_PROP: + case OP_PRUNE: + case OP_PRUNE_ARG: + case OP_RECURSE: + case OP_REF: + case OP_REFI: + case OP_REVERSE: + case OP_RREF: + case OP_SCOND: + case OP_SET_SOM: + case OP_SKIP: + case OP_SKIP_ARG: + case OP_SOD: + case OP_SOM: + case OP_THEN: + case OP_THEN_ARG: +#if defined SUPPORT_UTF || !defined COMPILE_PCRE8 + case OP_XCLASS: +#endif + return SSB_FAIL; + + /* We can ignore word boundary tests. */ + + case OP_WORD_BOUNDARY: + case OP_NOT_WORD_BOUNDARY: + tcode++; + break; + + /* If we hit a bracket or a positive lookahead assertion, recurse to set + bits from within the subpattern. If it can't find anything, we have to + give up. If it finds some mandatory character(s), we are done for this + branch. Otherwise, carry on scanning after the subpattern. */ + + case OP_BRA: + case OP_SBRA: + case OP_CBRA: + case OP_SCBRA: + case OP_BRAPOS: + case OP_SBRAPOS: + case OP_CBRAPOS: + case OP_SCBRAPOS: + case OP_ONCE: + case OP_ONCE_NC: + case OP_ASSERT: + rc = set_start_bits(tcode, start_bits, utf, cd); + if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; + if (rc == SSB_DONE) try_next = FALSE; else + { + do tcode += GET(tcode, 1); while (*tcode == OP_ALT); + tcode += 1 + LINK_SIZE; + } + break; + + /* If we hit ALT or KET, it means we haven't found anything mandatory in + this branch, though we might have found something optional. For ALT, we + continue with the next alternative, but we have to arrange that the final + result from subpattern is SSB_CONTINUE rather than SSB_DONE. For KET, + return SSB_CONTINUE: if this is the top level, that indicates failure, + but after a nested subpattern, it causes scanning to continue. */ + + case OP_ALT: + yield = SSB_CONTINUE; + try_next = FALSE; + break; + + case OP_KET: + case OP_KETRMAX: + case OP_KETRMIN: + case OP_KETRPOS: + return SSB_CONTINUE; + + /* Skip over callout */ + + case OP_CALLOUT: + tcode += 2 + 2*LINK_SIZE; + break; + + /* Skip over lookbehind and negative lookahead assertions */ + + case OP_ASSERT_NOT: + case OP_ASSERTBACK: + case OP_ASSERTBACK_NOT: + do tcode += GET(tcode, 1); while (*tcode == OP_ALT); + tcode += 1 + LINK_SIZE; + break; + + /* BRAZERO does the bracket, but carries on. */ + + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + rc = set_start_bits(++tcode, start_bits, utf, cd); + if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; +/* ========================================================================= + See the comment at the head of this function concerning the next line, + which was an old fudge for the benefit of OS/2. + dummy = 1; + ========================================================================= */ + do tcode += GET(tcode,1); while (*tcode == OP_ALT); + tcode += 1 + LINK_SIZE; + break; + + /* SKIPZERO skips the bracket. */ + + case OP_SKIPZERO: + tcode++; + do tcode += GET(tcode,1); while (*tcode == OP_ALT); + tcode += 1 + LINK_SIZE; + break; + + /* Single-char * or ? sets the bit and tries the next item */ + + case OP_STAR: + case OP_MINSTAR: + case OP_POSSTAR: + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + tcode = set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); + break; + + case OP_STARI: + case OP_MINSTARI: + case OP_POSSTARI: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_POSQUERYI: + tcode = set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); + break; + + /* Single-char upto sets the bit and tries the next */ + + case OP_UPTO: + case OP_MINUPTO: + case OP_POSUPTO: + tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, FALSE, cd, utf); + break; + + case OP_UPTOI: + case OP_MINUPTOI: + case OP_POSUPTOI: + tcode = set_table_bit(start_bits, tcode + 1 + IMM2_SIZE, TRUE, cd, utf); + break; + + /* At least one single char sets the bit and stops */ + + case OP_EXACT: + tcode += IMM2_SIZE; + /* Fall through */ + case OP_CHAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSPLUS: + (void)set_table_bit(start_bits, tcode + 1, FALSE, cd, utf); + try_next = FALSE; + break; + + case OP_EXACTI: + tcode += IMM2_SIZE; + /* Fall through */ + case OP_CHARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_POSPLUSI: + (void)set_table_bit(start_bits, tcode + 1, TRUE, cd, utf); + try_next = FALSE; + break; + + /* Special spacing and line-terminating items. These recognize specific + lists of characters. The difference between VSPACE and ANYNL is that the + latter can match the two-character CRLF sequence, but that is not + relevant for finding the first character, so their code here is + identical. */ + + case OP_HSPACE: + SET_BIT(0x09); + SET_BIT(0x20); +#ifdef SUPPORT_UTF + if (utf) + { +#ifdef COMPILE_PCRE8 + SET_BIT(0xC2); /* For U+00A0 */ + SET_BIT(0xE1); /* For U+1680, U+180E */ + SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ + SET_BIT(0xE3); /* For U+3000 */ +#endif +#ifdef COMPILE_PCRE16 + SET_BIT(0xA0); + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + else +#endif /* SUPPORT_UTF */ + { + SET_BIT(0xA0); +#ifdef COMPILE_PCRE16 + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + try_next = FALSE; + break; + + case OP_ANYNL: + case OP_VSPACE: + SET_BIT(0x0A); + SET_BIT(0x0B); + SET_BIT(0x0C); + SET_BIT(0x0D); +#ifdef SUPPORT_UTF + if (utf) + { +#ifdef COMPILE_PCRE8 + SET_BIT(0xC2); /* For U+0085 */ + SET_BIT(0xE2); /* For U+2028, U+2029 */ +#endif +#ifdef COMPILE_PCRE16 + SET_BIT(0x85); + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + else +#endif /* SUPPORT_UTF */ + { + SET_BIT(0x85); +#ifdef COMPILE_PCRE16 + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + try_next = FALSE; + break; + + /* Single character types set the bits and stop. Note that if PCRE_UCP + is set, we do not see these op codes because \d etc are converted to + properties. Therefore, these apply in the case when only characters less + than 256 are recognized to match the types. */ + + case OP_NOT_DIGIT: + set_nottype_bits(start_bits, cbit_digit, table_limit, cd); + try_next = FALSE; + break; + + case OP_DIGIT: + set_type_bits(start_bits, cbit_digit, table_limit, cd); + try_next = FALSE; + break; + + /* The cbit_space table has vertical tab as whitespace; we have to + ensure it is set as not whitespace. */ + + case OP_NOT_WHITESPACE: + set_nottype_bits(start_bits, cbit_space, table_limit, cd); + start_bits[1] |= 0x08; + try_next = FALSE; + break; + + /* The cbit_space table has vertical tab as whitespace; we have to + not set it from the table. */ + + case OP_WHITESPACE: + c = start_bits[1]; /* Save in case it was already set */ + set_type_bits(start_bits, cbit_space, table_limit, cd); + start_bits[1] = (start_bits[1] & ~0x08) | c; + try_next = FALSE; + break; + + case OP_NOT_WORDCHAR: + set_nottype_bits(start_bits, cbit_word, table_limit, cd); + try_next = FALSE; + break; + + case OP_WORDCHAR: + set_type_bits(start_bits, cbit_word, table_limit, cd); + try_next = FALSE; + break; + + /* One or more character type fudges the pointer and restarts, knowing + it will hit a single character type and stop there. */ + + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSPLUS: + tcode++; + break; + + case OP_TYPEEXACT: + tcode += 1 + IMM2_SIZE; + break; + + /* Zero or more repeats of character types set the bits and then + try again. */ + + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEPOSUPTO: + tcode += IMM2_SIZE; /* Fall through */ + + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPOSSTAR: + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSQUERY: + switch(tcode[1]) + { + default: + case OP_ANY: + case OP_ALLANY: + return SSB_FAIL; + + case OP_HSPACE: + SET_BIT(0x09); + SET_BIT(0x20); +#ifdef COMPILE_PCRE8 + if (utf) + { +#ifdef COMPILE_PCRE8 + SET_BIT(0xC2); /* For U+00A0 */ + SET_BIT(0xE1); /* For U+1680, U+180E */ + SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */ + SET_BIT(0xE3); /* For U+3000 */ +#endif +#ifdef COMPILE_PCRE16 + SET_BIT(0xA0); + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + else +#endif /* SUPPORT_UTF */ + SET_BIT(0xA0); + break; + + case OP_ANYNL: + case OP_VSPACE: + SET_BIT(0x0A); + SET_BIT(0x0B); + SET_BIT(0x0C); + SET_BIT(0x0D); +#ifdef COMPILE_PCRE8 + if (utf) + { +#ifdef COMPILE_PCRE8 + SET_BIT(0xC2); /* For U+0085 */ + SET_BIT(0xE2); /* For U+2028, U+2029 */ +#endif +#ifdef COMPILE_PCRE16 + SET_BIT(0x85); + SET_BIT(0xFF); /* For characters > 255 */ +#endif + } + else +#endif /* SUPPORT_UTF */ + SET_BIT(0x85); + break; + + case OP_NOT_DIGIT: + set_nottype_bits(start_bits, cbit_digit, table_limit, cd); + break; + + case OP_DIGIT: + set_type_bits(start_bits, cbit_digit, table_limit, cd); + break; + + /* The cbit_space table has vertical tab as whitespace; we have to + ensure it gets set as not whitespace. */ + + case OP_NOT_WHITESPACE: + set_nottype_bits(start_bits, cbit_space, table_limit, cd); + start_bits[1] |= 0x08; + break; + + /* The cbit_space table has vertical tab as whitespace; we have to + avoid setting it. */ + + case OP_WHITESPACE: + c = start_bits[1]; /* Save in case it was already set */ + set_type_bits(start_bits, cbit_space, table_limit, cd); + start_bits[1] = (start_bits[1] & ~0x08) | c; + break; + + case OP_NOT_WORDCHAR: + set_nottype_bits(start_bits, cbit_word, table_limit, cd); + break; + + case OP_WORDCHAR: + set_type_bits(start_bits, cbit_word, table_limit, cd); + break; + } + + tcode += 2; + break; + + /* Character class where all the information is in a bit map: set the + bits and either carry on or not, according to the repeat count. If it was + a negative class, and we are operating with UTF-8 characters, any byte + with a value >= 0xc4 is a potentially valid starter because it starts a + character with a value > 255. */ + + case OP_NCLASS: +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 + if (utf) + { + start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ + memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ + } +#endif +#ifdef COMPILE_PCRE16 + SET_BIT(0xFF); /* For characters > 255 */ +#endif + /* Fall through */ + + case OP_CLASS: + { + pcre_uint8 *map; + tcode++; + map = (pcre_uint8 *)tcode; + + /* In UTF-8 mode, the bits in a bit map correspond to character + values, not to byte values. However, the bit map we are constructing is + for byte values. So we have to do a conversion for characters whose + value is > 127. In fact, there are only two possible starting bytes for + characters in the range 128 - 255. */ + +#if defined SUPPORT_UTF && defined COMPILE_PCRE8 + if (utf) + { + for (c = 0; c < 16; c++) start_bits[c] |= map[c]; + for (c = 128; c < 256; c++) + { + if ((map[c/8] && (1 << (c&7))) != 0) + { + int d = (c >> 6) | 0xc0; /* Set bit for this starter */ + start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ + c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */ + } + } + } + else +#endif + { + /* In non-UTF-8 mode, the two bit maps are completely compatible. */ + for (c = 0; c < 32; c++) start_bits[c] |= map[c]; + } + + /* Advance past the bit map, and act on what follows. For a zero + minimum repeat, continue; otherwise stop processing. */ + + tcode += 32 / sizeof(pcre_uchar); + switch (*tcode) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRQUERY: + case OP_CRMINQUERY: + tcode++; + break; + + case OP_CRRANGE: + case OP_CRMINRANGE: + if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE; + else try_next = FALSE; + break; + + default: + try_next = FALSE; + break; + } + } + break; /* End of bitmap class handling */ + + } /* End of switch */ + } /* End of try_next loop */ + + code += GET(code, 1); /* Advance to next branch */ + } +while (*code == OP_ALT); +return yield; +} + + + + + +/************************************************* +* Study a compiled expression * +*************************************************/ + +/* This function is handed a compiled expression that it must study to produce +information that will speed up the matching. It returns a pcre[16]_extra block +which then gets handed back to pcre_exec(). + +Arguments: + re points to the compiled expression + options contains option bits + errorptr points to where to place error messages; + set NULL unless error + +Returns: pointer to a pcre[16]_extra block, with study_data filled in and + the appropriate flags set; + NULL on error or if no optimization possible +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION +pcre_study(const pcre *external_re, int options, const char **errorptr) +#else +PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION +pcre16_study(const pcre16 *external_re, int options, const char **errorptr) +#endif +{ +int min; +BOOL bits_set = FALSE; +pcre_uint8 start_bits[32]; +PUBL(extra) *extra = NULL; +pcre_study_data *study; +const pcre_uint8 *tables; +pcre_uchar *code; +compile_data compile_block; +const REAL_PCRE *re = (const REAL_PCRE *)external_re; + +*errorptr = NULL; + +if (re == NULL || re->magic_number != MAGIC_NUMBER) + { + *errorptr = "argument is not a compiled regular expression"; + return NULL; + } + +if ((re->flags & PCRE_MODE) == 0) + { +#ifdef COMPILE_PCRE8 + *errorptr = "argument is compiled in 16 bit mode"; +#else + *errorptr = "argument is compiled in 8 bit mode"; +#endif + return NULL; + } + +if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) + { + *errorptr = "unknown or incorrect option bit(s) set"; + return NULL; + } + +code = (pcre_uchar *)re + re->name_table_offset + + (re->name_count * re->name_entry_size); + +/* For an anchored pattern, or an unanchored pattern that has a first char, or +a multiline pattern that matches only at "line starts", there is no point in +seeking a list of starting bytes. */ + +if ((re->options & PCRE_ANCHORED) == 0 && + (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) == 0) + { + int rc; + + /* Set the character tables in the block that is passed around */ + + tables = re->tables; + +#ifdef COMPILE_PCRE8 + if (tables == NULL) + (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, + (void *)(&tables)); +#else + if (tables == NULL) + (void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, + (void *)(&tables)); +#endif + + compile_block.lcc = tables + lcc_offset; + compile_block.fcc = tables + fcc_offset; + compile_block.cbits = tables + cbits_offset; + compile_block.ctypes = tables + ctypes_offset; + + /* See if we can find a fixed set of initial characters for the pattern. */ + + memset(start_bits, 0, 32 * sizeof(pcre_uint8)); + rc = set_start_bits(code, start_bits, (re->options & PCRE_UTF8) != 0, + &compile_block); + bits_set = rc == SSB_DONE; + if (rc == SSB_UNKNOWN) + { + *errorptr = "internal error: opcode not recognized"; + return NULL; + } + } + +/* Find the minimum length of subject string. */ + +switch(min = find_minlength(code, code, re->options, 0)) + { + case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; + case -3: *errorptr = "internal error: opcode not recognized"; return NULL; + default: break; + } + +/* If a set of starting bytes has been identified, or if the minimum length is +greater than zero, or if JIT optimization has been requested, get a +pcre[16]_extra block and a pcre_study_data block. The study data is put in the +latter, which is pointed to by the former, which may also get additional data +set later by the calling program. At the moment, the size of pcre_study_data +is fixed. We nevertheless save it in a field for returning via the +pcre_fullinfo() function so that if it becomes variable in the future, +we don't have to change that code. */ + +if (bits_set || min > 0 +#ifdef SUPPORT_JIT + || (options & PCRE_STUDY_JIT_COMPILE) != 0 +#endif + ) + { + extra = (PUBL(extra) *)(PUBL(malloc)) + (sizeof(PUBL(extra)) + sizeof(pcre_study_data)); + if (extra == NULL) + { + *errorptr = "failed to get memory"; + return NULL; + } + + study = (pcre_study_data *)((char *)extra + sizeof(PUBL(extra))); + extra->flags = PCRE_EXTRA_STUDY_DATA; + extra->study_data = study; + + study->size = sizeof(pcre_study_data); + study->flags = 0; + + /* Set the start bits always, to avoid unset memory errors if the + study data is written to a file, but set the flag only if any of the bits + are set, to save time looking when none are. */ + + if (bits_set) + { + study->flags |= PCRE_STUDY_MAPPED; + memcpy(study->start_bits, start_bits, sizeof(start_bits)); + } + else memset(study->start_bits, 0, 32 * sizeof(pcre_uint8)); + +#ifdef PCRE_DEBUG + if (bits_set) + { + pcre_uint8 *ptr = start_bits; + int i; + + printf("Start bits:\n"); + for (i = 0; i < 32; i++) + printf("%3d: %02x%s", i * 8, *ptr++, ((i + 1) & 0x7) != 0? " " : "\n"); + } +#endif + + /* Always set the minlength value in the block, because the JIT compiler + makes use of it. However, don't set the bit unless the length is greater than + zero - the interpretive pcre_exec() and pcre_dfa_exec() needn't waste time + checking the zero case. */ + + if (min > 0) + { + study->flags |= PCRE_STUDY_MINLEN; + study->minlength = min; + } + else study->minlength = 0; + + /* If JIT support was compiled and requested, attempt the JIT compilation. + If no starting bytes were found, and the minimum length is zero, and JIT + compilation fails, abandon the extra block and return NULL. */ + +#ifdef SUPPORT_JIT + extra->executable_jit = NULL; + if ((options & PCRE_STUDY_JIT_COMPILE) != 0) PRIV(jit_compile)(re, extra); + if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0) + { +#ifdef COMPILE_PCRE8 + pcre_free_study(extra); +#endif +#ifdef COMPILE_PCRE16 + pcre16_free_study(extra); +#endif + extra = NULL; + } +#endif + } + +return extra; +} + + +/************************************************* +* Free the study data * +*************************************************/ + +/* This function frees the memory that was obtained by pcre_study(). + +Argument: a pointer to the pcre[16]_extra block +Returns: nothing +*/ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN void +pcre_free_study(pcre_extra *extra) +#else +PCRE_EXP_DEFN void +pcre16_free_study(pcre16_extra *extra) +#endif +{ +if (extra == NULL) + return; +#ifdef SUPPORT_JIT +if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && + extra->executable_jit != NULL) + PRIV(jit_free)(extra->executable_jit); +#endif +PUBL(free)(extra); +} + +/* End of pcre_study.c */ diff --git a/src/3rdparty/pcre/pcre_tables.c b/src/3rdparty/pcre/pcre_tables.c new file mode 100644 index 0000000000..9e449f8888 --- /dev/null +++ b/src/3rdparty/pcre/pcre_tables.c @@ -0,0 +1,568 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +#ifndef PCRE_INCLUDED + +/* This module contains some fixed tables that are used by more than one of the +PCRE code modules. The tables are also #included by the pcretest program, which +uses macros to change their names from _pcre_xxx to xxxx, thereby avoiding name +clashes with the library. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +#endif /* PCRE_INCLUDED */ + +/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that +the definition is next to the definition of the opcodes in pcre_internal.h. */ + +const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS }; + + + +/************************************************* +* Tables for UTF-8 support * +*************************************************/ + +/* These are the breakpoints for different numbers of bytes in a UTF-8 +character. */ + +#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \ + || (defined PCRE_INCLUDED && defined SUPPORT_PCRE16) + +/* These tables are also required by pcretest in 16 bit mode. */ + +const int PRIV(utf8_table1)[] = + { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff}; + +const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int); + +/* These are the indicator bits and the mask for the data bits to set in the +first byte of a character, indexed by the number of additional bytes. */ + +const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc}; +const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01}; + +/* Table of the number of extra bytes, indexed by the first byte masked with +0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */ + +const pcre_uint8 PRIV(utf8_table4)[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; + +#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/ + +#ifdef SUPPORT_UTF + +/* Table to translate from particular type value to the general value. */ + +const int PRIV(ucp_gentype)[] = { + ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */ + ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */ + ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */ + ucp_N, ucp_N, ucp_N, /* Nd, Nl, No */ + ucp_P, ucp_P, ucp_P, ucp_P, ucp_P, /* Pc, Pd, Pe, Pf, Pi */ + ucp_P, ucp_P, /* Ps, Po */ + ucp_S, ucp_S, ucp_S, ucp_S, /* Sc, Sk, Sm, So */ + ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */ +}; + +#ifdef SUPPORT_JIT +/* This table reverses PRIV(ucp_gentype). We can save the cost +of a memory load. */ + +const int PRIV(ucp_typerange)[] = { + ucp_Cc, ucp_Cs, + ucp_Ll, ucp_Lu, + ucp_Mc, ucp_Mn, + ucp_Nd, ucp_No, + ucp_Pc, ucp_Ps, + ucp_Sc, ucp_So, + ucp_Zl, ucp_Zs, +}; +#endif /* SUPPORT_JIT */ + +/* The pcre_utt[] table below translates Unicode property names into type and +code values. It is searched by binary chop, so must be in collating sequence of +name. Originally, the table contained pointers to the name strings in the first +field of each entry. However, that leads to a large number of relocations when +a shared library is dynamically loaded. A significant reduction is made by +putting all the names into a single, large string and then using offsets in the +table itself. Maintenance is more error-prone, but frequent changes to this +data are unlikely. + +July 2008: There is now a script called maint/GenerateUtt.py that can be used +to generate this data automatically instead of maintaining it by hand. + +The script was updated in March 2009 to generate a new EBCDIC-compliant +version. Like all other character and string literals that are compared against +the regular expression pattern, we must use STR_ macros instead of literal +strings to make sure that UTF-8 support works on EBCDIC platforms. */ + +#define STRING_Any0 STR_A STR_n STR_y "\0" +#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0" +#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0" +#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0" +#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0" +#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0" +#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0" +#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0" +#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0" +#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0" +#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0" +#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0" +#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0" +#define STRING_C0 STR_C "\0" +#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0" +#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0" +#define STRING_Cc0 STR_C STR_c "\0" +#define STRING_Cf0 STR_C STR_f "\0" +#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0" +#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0" +#define STRING_Cn0 STR_C STR_n "\0" +#define STRING_Co0 STR_C STR_o "\0" +#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0" +#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0" +#define STRING_Cs0 STR_C STR_s "\0" +#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0" +#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0" +#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0" +#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0" +#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0" +#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" +#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0" +#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0" +#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0" +#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0" +#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0" +#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0" +#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0" +#define STRING_Han0 STR_H STR_a STR_n "\0" +#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0" +#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0" +#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0" +#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0" +#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0" +#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0" +#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0" +#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0" +#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0" +#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0" +#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0" +#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0" +#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0" +#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0" +#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0" +#define STRING_L0 STR_L "\0" +#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0" +#define STRING_Lao0 STR_L STR_a STR_o "\0" +#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0" +#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0" +#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0" +#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0" +#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0" +#define STRING_Ll0 STR_L STR_l "\0" +#define STRING_Lm0 STR_L STR_m "\0" +#define STRING_Lo0 STR_L STR_o "\0" +#define STRING_Lt0 STR_L STR_t "\0" +#define STRING_Lu0 STR_L STR_u "\0" +#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0" +#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0" +#define STRING_M0 STR_M "\0" +#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0" +#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0" +#define STRING_Mc0 STR_M STR_c "\0" +#define STRING_Me0 STR_M STR_e "\0" +#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0" +#define STRING_Mn0 STR_M STR_n "\0" +#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0" +#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0" +#define STRING_N0 STR_N "\0" +#define STRING_Nd0 STR_N STR_d "\0" +#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0" +#define STRING_Nko0 STR_N STR_k STR_o "\0" +#define STRING_Nl0 STR_N STR_l "\0" +#define STRING_No0 STR_N STR_o "\0" +#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0" +#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0" +#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0" +#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0" +#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0" +#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0" +#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0" +#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0" +#define STRING_P0 STR_P "\0" +#define STRING_Pc0 STR_P STR_c "\0" +#define STRING_Pd0 STR_P STR_d "\0" +#define STRING_Pe0 STR_P STR_e "\0" +#define STRING_Pf0 STR_P STR_f "\0" +#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0" +#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0" +#define STRING_Pi0 STR_P STR_i "\0" +#define STRING_Po0 STR_P STR_o "\0" +#define STRING_Ps0 STR_P STR_s "\0" +#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0" +#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0" +#define STRING_S0 STR_S "\0" +#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0" +#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0" +#define STRING_Sc0 STR_S STR_c "\0" +#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0" +#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0" +#define STRING_Sk0 STR_S STR_k "\0" +#define STRING_Sm0 STR_S STR_m "\0" +#define STRING_So0 STR_S STR_o "\0" +#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0" +#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0" +#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0" +#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0" +#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0" +#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0" +#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0" +#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0" +#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0" +#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0" +#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0" +#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0" +#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0" +#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0" +#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0" +#define STRING_Vai0 STR_V STR_a STR_i "\0" +#define STRING_Xan0 STR_X STR_a STR_n "\0" +#define STRING_Xps0 STR_X STR_p STR_s "\0" +#define STRING_Xsp0 STR_X STR_s STR_p "\0" +#define STRING_Xwd0 STR_X STR_w STR_d "\0" +#define STRING_Yi0 STR_Y STR_i "\0" +#define STRING_Z0 STR_Z "\0" +#define STRING_Zl0 STR_Z STR_l "\0" +#define STRING_Zp0 STR_Z STR_p "\0" +#define STRING_Zs0 STR_Z STR_s "\0" + +const char PRIV(utt_names)[] = + STRING_Any0 + STRING_Arabic0 + STRING_Armenian0 + STRING_Avestan0 + STRING_Balinese0 + STRING_Bamum0 + STRING_Batak0 + STRING_Bengali0 + STRING_Bopomofo0 + STRING_Brahmi0 + STRING_Braille0 + STRING_Buginese0 + STRING_Buhid0 + STRING_C0 + STRING_Canadian_Aboriginal0 + STRING_Carian0 + STRING_Cc0 + STRING_Cf0 + STRING_Cham0 + STRING_Cherokee0 + STRING_Cn0 + STRING_Co0 + STRING_Common0 + STRING_Coptic0 + STRING_Cs0 + STRING_Cuneiform0 + STRING_Cypriot0 + STRING_Cyrillic0 + STRING_Deseret0 + STRING_Devanagari0 + STRING_Egyptian_Hieroglyphs0 + STRING_Ethiopic0 + STRING_Georgian0 + STRING_Glagolitic0 + STRING_Gothic0 + STRING_Greek0 + STRING_Gujarati0 + STRING_Gurmukhi0 + STRING_Han0 + STRING_Hangul0 + STRING_Hanunoo0 + STRING_Hebrew0 + STRING_Hiragana0 + STRING_Imperial_Aramaic0 + STRING_Inherited0 + STRING_Inscriptional_Pahlavi0 + STRING_Inscriptional_Parthian0 + STRING_Javanese0 + STRING_Kaithi0 + STRING_Kannada0 + STRING_Katakana0 + STRING_Kayah_Li0 + STRING_Kharoshthi0 + STRING_Khmer0 + STRING_L0 + STRING_L_AMPERSAND0 + STRING_Lao0 + STRING_Latin0 + STRING_Lepcha0 + STRING_Limbu0 + STRING_Linear_B0 + STRING_Lisu0 + STRING_Ll0 + STRING_Lm0 + STRING_Lo0 + STRING_Lt0 + STRING_Lu0 + STRING_Lycian0 + STRING_Lydian0 + STRING_M0 + STRING_Malayalam0 + STRING_Mandaic0 + STRING_Mc0 + STRING_Me0 + STRING_Meetei_Mayek0 + STRING_Mn0 + STRING_Mongolian0 + STRING_Myanmar0 + STRING_N0 + STRING_Nd0 + STRING_New_Tai_Lue0 + STRING_Nko0 + STRING_Nl0 + STRING_No0 + STRING_Ogham0 + STRING_Ol_Chiki0 + STRING_Old_Italic0 + STRING_Old_Persian0 + STRING_Old_South_Arabian0 + STRING_Old_Turkic0 + STRING_Oriya0 + STRING_Osmanya0 + STRING_P0 + STRING_Pc0 + STRING_Pd0 + STRING_Pe0 + STRING_Pf0 + STRING_Phags_Pa0 + STRING_Phoenician0 + STRING_Pi0 + STRING_Po0 + STRING_Ps0 + STRING_Rejang0 + STRING_Runic0 + STRING_S0 + STRING_Samaritan0 + STRING_Saurashtra0 + STRING_Sc0 + STRING_Shavian0 + STRING_Sinhala0 + STRING_Sk0 + STRING_Sm0 + STRING_So0 + STRING_Sundanese0 + STRING_Syloti_Nagri0 + STRING_Syriac0 + STRING_Tagalog0 + STRING_Tagbanwa0 + STRING_Tai_Le0 + STRING_Tai_Tham0 + STRING_Tai_Viet0 + STRING_Tamil0 + STRING_Telugu0 + STRING_Thaana0 + STRING_Thai0 + STRING_Tibetan0 + STRING_Tifinagh0 + STRING_Ugaritic0 + STRING_Vai0 + STRING_Xan0 + STRING_Xps0 + STRING_Xsp0 + STRING_Xwd0 + STRING_Yi0 + STRING_Z0 + STRING_Zl0 + STRING_Zp0 + STRING_Zs0; + +const ucp_type_table PRIV(utt)[] = { + { 0, PT_ANY, 0 }, + { 4, PT_SC, ucp_Arabic }, + { 11, PT_SC, ucp_Armenian }, + { 20, PT_SC, ucp_Avestan }, + { 28, PT_SC, ucp_Balinese }, + { 37, PT_SC, ucp_Bamum }, + { 43, PT_SC, ucp_Batak }, + { 49, PT_SC, ucp_Bengali }, + { 57, PT_SC, ucp_Bopomofo }, + { 66, PT_SC, ucp_Brahmi }, + { 73, PT_SC, ucp_Braille }, + { 81, PT_SC, ucp_Buginese }, + { 90, PT_SC, ucp_Buhid }, + { 96, PT_GC, ucp_C }, + { 98, PT_SC, ucp_Canadian_Aboriginal }, + { 118, PT_SC, ucp_Carian }, + { 125, PT_PC, ucp_Cc }, + { 128, PT_PC, ucp_Cf }, + { 131, PT_SC, ucp_Cham }, + { 136, PT_SC, ucp_Cherokee }, + { 145, PT_PC, ucp_Cn }, + { 148, PT_PC, ucp_Co }, + { 151, PT_SC, ucp_Common }, + { 158, PT_SC, ucp_Coptic }, + { 165, PT_PC, ucp_Cs }, + { 168, PT_SC, ucp_Cuneiform }, + { 178, PT_SC, ucp_Cypriot }, + { 186, PT_SC, ucp_Cyrillic }, + { 195, PT_SC, ucp_Deseret }, + { 203, PT_SC, ucp_Devanagari }, + { 214, PT_SC, ucp_Egyptian_Hieroglyphs }, + { 235, PT_SC, ucp_Ethiopic }, + { 244, PT_SC, ucp_Georgian }, + { 253, PT_SC, ucp_Glagolitic }, + { 264, PT_SC, ucp_Gothic }, + { 271, PT_SC, ucp_Greek }, + { 277, PT_SC, ucp_Gujarati }, + { 286, PT_SC, ucp_Gurmukhi }, + { 295, PT_SC, ucp_Han }, + { 299, PT_SC, ucp_Hangul }, + { 306, PT_SC, ucp_Hanunoo }, + { 314, PT_SC, ucp_Hebrew }, + { 321, PT_SC, ucp_Hiragana }, + { 330, PT_SC, ucp_Imperial_Aramaic }, + { 347, PT_SC, ucp_Inherited }, + { 357, PT_SC, ucp_Inscriptional_Pahlavi }, + { 379, PT_SC, ucp_Inscriptional_Parthian }, + { 402, PT_SC, ucp_Javanese }, + { 411, PT_SC, ucp_Kaithi }, + { 418, PT_SC, ucp_Kannada }, + { 426, PT_SC, ucp_Katakana }, + { 435, PT_SC, ucp_Kayah_Li }, + { 444, PT_SC, ucp_Kharoshthi }, + { 455, PT_SC, ucp_Khmer }, + { 461, PT_GC, ucp_L }, + { 463, PT_LAMP, 0 }, + { 466, PT_SC, ucp_Lao }, + { 470, PT_SC, ucp_Latin }, + { 476, PT_SC, ucp_Lepcha }, + { 483, PT_SC, ucp_Limbu }, + { 489, PT_SC, ucp_Linear_B }, + { 498, PT_SC, ucp_Lisu }, + { 503, PT_PC, ucp_Ll }, + { 506, PT_PC, ucp_Lm }, + { 509, PT_PC, ucp_Lo }, + { 512, PT_PC, ucp_Lt }, + { 515, PT_PC, ucp_Lu }, + { 518, PT_SC, ucp_Lycian }, + { 525, PT_SC, ucp_Lydian }, + { 532, PT_GC, ucp_M }, + { 534, PT_SC, ucp_Malayalam }, + { 544, PT_SC, ucp_Mandaic }, + { 552, PT_PC, ucp_Mc }, + { 555, PT_PC, ucp_Me }, + { 558, PT_SC, ucp_Meetei_Mayek }, + { 571, PT_PC, ucp_Mn }, + { 574, PT_SC, ucp_Mongolian }, + { 584, PT_SC, ucp_Myanmar }, + { 592, PT_GC, ucp_N }, + { 594, PT_PC, ucp_Nd }, + { 597, PT_SC, ucp_New_Tai_Lue }, + { 609, PT_SC, ucp_Nko }, + { 613, PT_PC, ucp_Nl }, + { 616, PT_PC, ucp_No }, + { 619, PT_SC, ucp_Ogham }, + { 625, PT_SC, ucp_Ol_Chiki }, + { 634, PT_SC, ucp_Old_Italic }, + { 645, PT_SC, ucp_Old_Persian }, + { 657, PT_SC, ucp_Old_South_Arabian }, + { 675, PT_SC, ucp_Old_Turkic }, + { 686, PT_SC, ucp_Oriya }, + { 692, PT_SC, ucp_Osmanya }, + { 700, PT_GC, ucp_P }, + { 702, PT_PC, ucp_Pc }, + { 705, PT_PC, ucp_Pd }, + { 708, PT_PC, ucp_Pe }, + { 711, PT_PC, ucp_Pf }, + { 714, PT_SC, ucp_Phags_Pa }, + { 723, PT_SC, ucp_Phoenician }, + { 734, PT_PC, ucp_Pi }, + { 737, PT_PC, ucp_Po }, + { 740, PT_PC, ucp_Ps }, + { 743, PT_SC, ucp_Rejang }, + { 750, PT_SC, ucp_Runic }, + { 756, PT_GC, ucp_S }, + { 758, PT_SC, ucp_Samaritan }, + { 768, PT_SC, ucp_Saurashtra }, + { 779, PT_PC, ucp_Sc }, + { 782, PT_SC, ucp_Shavian }, + { 790, PT_SC, ucp_Sinhala }, + { 798, PT_PC, ucp_Sk }, + { 801, PT_PC, ucp_Sm }, + { 804, PT_PC, ucp_So }, + { 807, PT_SC, ucp_Sundanese }, + { 817, PT_SC, ucp_Syloti_Nagri }, + { 830, PT_SC, ucp_Syriac }, + { 837, PT_SC, ucp_Tagalog }, + { 845, PT_SC, ucp_Tagbanwa }, + { 854, PT_SC, ucp_Tai_Le }, + { 861, PT_SC, ucp_Tai_Tham }, + { 870, PT_SC, ucp_Tai_Viet }, + { 879, PT_SC, ucp_Tamil }, + { 885, PT_SC, ucp_Telugu }, + { 892, PT_SC, ucp_Thaana }, + { 899, PT_SC, ucp_Thai }, + { 904, PT_SC, ucp_Tibetan }, + { 912, PT_SC, ucp_Tifinagh }, + { 921, PT_SC, ucp_Ugaritic }, + { 930, PT_SC, ucp_Vai }, + { 934, PT_ALNUM, 0 }, + { 938, PT_PXSPACE, 0 }, + { 942, PT_SPACE, 0 }, + { 946, PT_WORD, 0 }, + { 950, PT_SC, ucp_Yi }, + { 953, PT_GC, ucp_Z }, + { 955, PT_PC, ucp_Zl }, + { 958, PT_PC, ucp_Zp }, + { 961, PT_PC, ucp_Zs } +}; + +const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); + +#endif /* SUPPORT_UTF */ + +/* End of pcre_tables.c */ diff --git a/src/3rdparty/pcre/pcre_ucd.c b/src/3rdparty/pcre/pcre_ucd.c new file mode 100644 index 0000000000..48fa486635 --- /dev/null +++ b/src/3rdparty/pcre/pcre_ucd.c @@ -0,0 +1,2981 @@ +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + +/* Unicode character database. */ +/* This file was autogenerated by the MultiStage2.py script. */ +/* Total size: 60384 bytes, block size: 128. */ + +/* The tables herein are needed only when UCP support is built */ +/* into PCRE. This module should not be referenced otherwise, so */ +/* it should not matter whether it is compiled or not. However */ +/* a comment was received about space saving - maybe the guy linked */ +/* all the modules rather than using a library - so we include a */ +/* condition to cut out the tables when not needed. But don't leave */ +/* a totally empty module because some compilers barf at that. */ +/* Instead, just supply small dummy tables. */ + +#ifndef SUPPORT_UCP +const ucd_record PRIV(ucd_records)[] = {{0,0,0 }}; +const pcre_uint8 PRIV(ucd_stage1)[] = {0}; +const pcre_uint16 PRIV(ucd_stage2)[] = {0}; +#else + +/* When recompiling tables with a new Unicode version, +please check types in the structure definition from pcre_internal.h: +typedef struct { +pcre_uint8 property_0; +pcre_uint8 property_1; +pcre_int32 property_2; +} ucd_record; */ + + +const ucd_record PRIV(ucd_records)[] = { /* 4320 bytes, record size 8 */ + { 9, 0, 0, }, /* 0 */ + { 9, 29, 0, }, /* 1 */ + { 9, 21, 0, }, /* 2 */ + { 9, 23, 0, }, /* 3 */ + { 9, 22, 0, }, /* 4 */ + { 9, 18, 0, }, /* 5 */ + { 9, 25, 0, }, /* 6 */ + { 9, 17, 0, }, /* 7 */ + { 9, 13, 0, }, /* 8 */ + { 33, 9, 32, }, /* 9 */ + { 9, 24, 0, }, /* 10 */ + { 9, 16, 0, }, /* 11 */ + { 33, 5, -32, }, /* 12 */ + { 9, 26, 0, }, /* 13 */ + { 33, 5, 0, }, /* 14 */ + { 9, 20, 0, }, /* 15 */ + { 9, 1, 0, }, /* 16 */ + { 9, 15, 0, }, /* 17 */ + { 9, 5, 743, }, /* 18 */ + { 9, 19, 0, }, /* 19 */ + { 33, 5, 121, }, /* 20 */ + { 33, 9, 1, }, /* 21 */ + { 33, 5, -1, }, /* 22 */ + { 33, 9, -199, }, /* 23 */ + { 33, 5, -232, }, /* 24 */ + { 33, 9, -121, }, /* 25 */ + { 33, 5, -300, }, /* 26 */ + { 33, 5, 195, }, /* 27 */ + { 33, 9, 210, }, /* 28 */ + { 33, 9, 206, }, /* 29 */ + { 33, 9, 205, }, /* 30 */ + { 33, 9, 79, }, /* 31 */ + { 33, 9, 202, }, /* 32 */ + { 33, 9, 203, }, /* 33 */ + { 33, 9, 207, }, /* 34 */ + { 33, 5, 97, }, /* 35 */ + { 33, 9, 211, }, /* 36 */ + { 33, 9, 209, }, /* 37 */ + { 33, 5, 163, }, /* 38 */ + { 33, 9, 213, }, /* 39 */ + { 33, 5, 130, }, /* 40 */ + { 33, 9, 214, }, /* 41 */ + { 33, 9, 218, }, /* 42 */ + { 33, 9, 217, }, /* 43 */ + { 33, 9, 219, }, /* 44 */ + { 33, 7, 0, }, /* 45 */ + { 33, 5, 56, }, /* 46 */ + { 33, 9, 2, }, /* 47 */ + { 33, 8, -1, }, /* 48 */ + { 33, 5, -2, }, /* 49 */ + { 33, 5, -79, }, /* 50 */ + { 33, 9, -97, }, /* 51 */ + { 33, 9, -56, }, /* 52 */ + { 33, 9, -130, }, /* 53 */ + { 33, 9, 10795, }, /* 54 */ + { 33, 9, -163, }, /* 55 */ + { 33, 9, 10792, }, /* 56 */ + { 33, 5, 10815, }, /* 57 */ + { 33, 9, -195, }, /* 58 */ + { 33, 9, 69, }, /* 59 */ + { 33, 9, 71, }, /* 60 */ + { 33, 5, 10783, }, /* 61 */ + { 33, 5, 10780, }, /* 62 */ + { 33, 5, 10782, }, /* 63 */ + { 33, 5, -210, }, /* 64 */ + { 33, 5, -206, }, /* 65 */ + { 33, 5, -205, }, /* 66 */ + { 33, 5, -202, }, /* 67 */ + { 33, 5, -203, }, /* 68 */ + { 33, 5, -207, }, /* 69 */ + { 33, 5, 42280, }, /* 70 */ + { 33, 5, -209, }, /* 71 */ + { 33, 5, -211, }, /* 72 */ + { 33, 5, 10743, }, /* 73 */ + { 33, 5, 10749, }, /* 74 */ + { 33, 5, -213, }, /* 75 */ + { 33, 5, -214, }, /* 76 */ + { 33, 5, 10727, }, /* 77 */ + { 33, 5, -218, }, /* 78 */ + { 33, 5, -69, }, /* 79 */ + { 33, 5, -217, }, /* 80 */ + { 33, 5, -71, }, /* 81 */ + { 33, 5, -219, }, /* 82 */ + { 33, 6, 0, }, /* 83 */ + { 9, 6, 0, }, /* 84 */ + { 3, 24, 0, }, /* 85 */ + { 27, 12, 0, }, /* 86 */ + { 27, 12, 84, }, /* 87 */ + { 19, 9, 1, }, /* 88 */ + { 19, 5, -1, }, /* 89 */ + { 19, 24, 0, }, /* 90 */ + { 9, 2, 0, }, /* 91 */ + { 19, 6, 0, }, /* 92 */ + { 19, 5, 130, }, /* 93 */ + { 19, 9, 38, }, /* 94 */ + { 19, 9, 37, }, /* 95 */ + { 19, 9, 64, }, /* 96 */ + { 19, 9, 63, }, /* 97 */ + { 19, 5, 0, }, /* 98 */ + { 19, 9, 32, }, /* 99 */ + { 19, 5, -38, }, /* 100 */ + { 19, 5, -37, }, /* 101 */ + { 19, 5, -32, }, /* 102 */ + { 19, 5, -31, }, /* 103 */ + { 19, 5, -64, }, /* 104 */ + { 19, 5, -63, }, /* 105 */ + { 19, 9, 8, }, /* 106 */ + { 19, 5, -62, }, /* 107 */ + { 19, 5, -57, }, /* 108 */ + { 19, 9, 0, }, /* 109 */ + { 19, 5, -47, }, /* 110 */ + { 19, 5, -54, }, /* 111 */ + { 19, 5, -8, }, /* 112 */ + { 10, 9, 1, }, /* 113 */ + { 10, 5, -1, }, /* 114 */ + { 19, 5, -86, }, /* 115 */ + { 19, 5, -80, }, /* 116 */ + { 19, 5, 7, }, /* 117 */ + { 19, 9, -60, }, /* 118 */ + { 19, 5, -96, }, /* 119 */ + { 19, 25, 0, }, /* 120 */ + { 19, 9, -7, }, /* 121 */ + { 19, 9, -130, }, /* 122 */ + { 12, 9, 80, }, /* 123 */ + { 12, 9, 32, }, /* 124 */ + { 12, 5, -32, }, /* 125 */ + { 12, 5, -80, }, /* 126 */ + { 12, 9, 1, }, /* 127 */ + { 12, 5, -1, }, /* 128 */ + { 12, 26, 0, }, /* 129 */ + { 12, 12, 0, }, /* 130 */ + { 12, 11, 0, }, /* 131 */ + { 12, 9, 15, }, /* 132 */ + { 12, 5, -15, }, /* 133 */ + { 1, 9, 48, }, /* 134 */ + { 1, 6, 0, }, /* 135 */ + { 1, 21, 0, }, /* 136 */ + { 1, 5, -48, }, /* 137 */ + { 1, 5, 0, }, /* 138 */ + { 1, 17, 0, }, /* 139 */ + { 25, 12, 0, }, /* 140 */ + { 25, 17, 0, }, /* 141 */ + { 25, 21, 0, }, /* 142 */ + { 25, 7, 0, }, /* 143 */ + { 0, 1, 0, }, /* 144 */ + { 0, 25, 0, }, /* 145 */ + { 0, 21, 0, }, /* 146 */ + { 0, 23, 0, }, /* 147 */ + { 0, 26, 0, }, /* 148 */ + { 0, 12, 0, }, /* 149 */ + { 0, 7, 0, }, /* 150 */ + { 0, 6, 0, }, /* 151 */ + { 0, 13, 0, }, /* 152 */ + { 49, 21, 0, }, /* 153 */ + { 49, 1, 0, }, /* 154 */ + { 49, 7, 0, }, /* 155 */ + { 49, 12, 0, }, /* 156 */ + { 55, 7, 0, }, /* 157 */ + { 55, 12, 0, }, /* 158 */ + { 63, 13, 0, }, /* 159 */ + { 63, 7, 0, }, /* 160 */ + { 63, 12, 0, }, /* 161 */ + { 63, 6, 0, }, /* 162 */ + { 63, 26, 0, }, /* 163 */ + { 63, 21, 0, }, /* 164 */ + { 89, 7, 0, }, /* 165 */ + { 89, 12, 0, }, /* 166 */ + { 89, 6, 0, }, /* 167 */ + { 89, 21, 0, }, /* 168 */ + { 94, 7, 0, }, /* 169 */ + { 94, 12, 0, }, /* 170 */ + { 94, 21, 0, }, /* 171 */ + { 14, 12, 0, }, /* 172 */ + { 14, 10, 0, }, /* 173 */ + { 14, 7, 0, }, /* 174 */ + { 14, 13, 0, }, /* 175 */ + { 14, 6, 0, }, /* 176 */ + { 2, 12, 0, }, /* 177 */ + { 2, 10, 0, }, /* 178 */ + { 2, 7, 0, }, /* 179 */ + { 2, 13, 0, }, /* 180 */ + { 2, 23, 0, }, /* 181 */ + { 2, 15, 0, }, /* 182 */ + { 2, 26, 0, }, /* 183 */ + { 21, 12, 0, }, /* 184 */ + { 21, 10, 0, }, /* 185 */ + { 21, 7, 0, }, /* 186 */ + { 21, 13, 0, }, /* 187 */ + { 20, 12, 0, }, /* 188 */ + { 20, 10, 0, }, /* 189 */ + { 20, 7, 0, }, /* 190 */ + { 20, 13, 0, }, /* 191 */ + { 20, 23, 0, }, /* 192 */ + { 43, 12, 0, }, /* 193 */ + { 43, 10, 0, }, /* 194 */ + { 43, 7, 0, }, /* 195 */ + { 43, 13, 0, }, /* 196 */ + { 43, 26, 0, }, /* 197 */ + { 43, 15, 0, }, /* 198 */ + { 53, 12, 0, }, /* 199 */ + { 53, 7, 0, }, /* 200 */ + { 53, 10, 0, }, /* 201 */ + { 53, 13, 0, }, /* 202 */ + { 53, 15, 0, }, /* 203 */ + { 53, 26, 0, }, /* 204 */ + { 53, 23, 0, }, /* 205 */ + { 54, 10, 0, }, /* 206 */ + { 54, 7, 0, }, /* 207 */ + { 54, 12, 0, }, /* 208 */ + { 54, 13, 0, }, /* 209 */ + { 54, 15, 0, }, /* 210 */ + { 54, 26, 0, }, /* 211 */ + { 28, 10, 0, }, /* 212 */ + { 28, 7, 0, }, /* 213 */ + { 28, 12, 0, }, /* 214 */ + { 28, 13, 0, }, /* 215 */ + { 36, 10, 0, }, /* 216 */ + { 36, 7, 0, }, /* 217 */ + { 36, 12, 0, }, /* 218 */ + { 36, 13, 0, }, /* 219 */ + { 36, 15, 0, }, /* 220 */ + { 36, 26, 0, }, /* 221 */ + { 47, 10, 0, }, /* 222 */ + { 47, 7, 0, }, /* 223 */ + { 47, 12, 0, }, /* 224 */ + { 47, 21, 0, }, /* 225 */ + { 56, 7, 0, }, /* 226 */ + { 56, 12, 0, }, /* 227 */ + { 56, 6, 0, }, /* 228 */ + { 56, 21, 0, }, /* 229 */ + { 56, 13, 0, }, /* 230 */ + { 32, 7, 0, }, /* 231 */ + { 32, 12, 0, }, /* 232 */ + { 32, 6, 0, }, /* 233 */ + { 32, 13, 0, }, /* 234 */ + { 57, 7, 0, }, /* 235 */ + { 57, 26, 0, }, /* 236 */ + { 57, 21, 0, }, /* 237 */ + { 57, 12, 0, }, /* 238 */ + { 57, 13, 0, }, /* 239 */ + { 57, 15, 0, }, /* 240 */ + { 57, 22, 0, }, /* 241 */ + { 57, 18, 0, }, /* 242 */ + { 57, 10, 0, }, /* 243 */ + { 38, 7, 0, }, /* 244 */ + { 38, 10, 0, }, /* 245 */ + { 38, 12, 0, }, /* 246 */ + { 38, 13, 0, }, /* 247 */ + { 38, 21, 0, }, /* 248 */ + { 38, 26, 0, }, /* 249 */ + { 16, 9, 7264, }, /* 250 */ + { 16, 7, 0, }, /* 251 */ + { 16, 6, 0, }, /* 252 */ + { 23, 7, 0, }, /* 253 */ + { 15, 7, 0, }, /* 254 */ + { 15, 12, 0, }, /* 255 */ + { 15, 26, 0, }, /* 256 */ + { 15, 21, 0, }, /* 257 */ + { 15, 15, 0, }, /* 258 */ + { 8, 7, 0, }, /* 259 */ + { 7, 17, 0, }, /* 260 */ + { 7, 7, 0, }, /* 261 */ + { 7, 21, 0, }, /* 262 */ + { 40, 29, 0, }, /* 263 */ + { 40, 7, 0, }, /* 264 */ + { 40, 22, 0, }, /* 265 */ + { 40, 18, 0, }, /* 266 */ + { 45, 7, 0, }, /* 267 */ + { 45, 14, 0, }, /* 268 */ + { 50, 7, 0, }, /* 269 */ + { 50, 12, 0, }, /* 270 */ + { 24, 7, 0, }, /* 271 */ + { 24, 12, 0, }, /* 272 */ + { 6, 7, 0, }, /* 273 */ + { 6, 12, 0, }, /* 274 */ + { 51, 7, 0, }, /* 275 */ + { 51, 12, 0, }, /* 276 */ + { 31, 7, 0, }, /* 277 */ + { 31, 1, 0, }, /* 278 */ + { 31, 10, 0, }, /* 279 */ + { 31, 12, 0, }, /* 280 */ + { 31, 21, 0, }, /* 281 */ + { 31, 6, 0, }, /* 282 */ + { 31, 23, 0, }, /* 283 */ + { 31, 13, 0, }, /* 284 */ + { 31, 15, 0, }, /* 285 */ + { 37, 21, 0, }, /* 286 */ + { 37, 17, 0, }, /* 287 */ + { 37, 12, 0, }, /* 288 */ + { 37, 29, 0, }, /* 289 */ + { 37, 13, 0, }, /* 290 */ + { 37, 7, 0, }, /* 291 */ + { 37, 6, 0, }, /* 292 */ + { 34, 7, 0, }, /* 293 */ + { 34, 12, 0, }, /* 294 */ + { 34, 10, 0, }, /* 295 */ + { 34, 26, 0, }, /* 296 */ + { 34, 21, 0, }, /* 297 */ + { 34, 13, 0, }, /* 298 */ + { 52, 7, 0, }, /* 299 */ + { 39, 7, 0, }, /* 300 */ + { 39, 10, 0, }, /* 301 */ + { 39, 13, 0, }, /* 302 */ + { 39, 15, 0, }, /* 303 */ + { 39, 26, 0, }, /* 304 */ + { 31, 26, 0, }, /* 305 */ + { 5, 7, 0, }, /* 306 */ + { 5, 12, 0, }, /* 307 */ + { 5, 10, 0, }, /* 308 */ + { 5, 21, 0, }, /* 309 */ + { 90, 7, 0, }, /* 310 */ + { 90, 10, 0, }, /* 311 */ + { 90, 12, 0, }, /* 312 */ + { 90, 13, 0, }, /* 313 */ + { 90, 21, 0, }, /* 314 */ + { 90, 6, 0, }, /* 315 */ + { 61, 12, 0, }, /* 316 */ + { 61, 10, 0, }, /* 317 */ + { 61, 7, 0, }, /* 318 */ + { 61, 13, 0, }, /* 319 */ + { 61, 21, 0, }, /* 320 */ + { 61, 26, 0, }, /* 321 */ + { 75, 12, 0, }, /* 322 */ + { 75, 10, 0, }, /* 323 */ + { 75, 7, 0, }, /* 324 */ + { 75, 13, 0, }, /* 325 */ + { 92, 7, 0, }, /* 326 */ + { 92, 12, 0, }, /* 327 */ + { 92, 10, 0, }, /* 328 */ + { 92, 21, 0, }, /* 329 */ + { 69, 7, 0, }, /* 330 */ + { 69, 10, 0, }, /* 331 */ + { 69, 12, 0, }, /* 332 */ + { 69, 21, 0, }, /* 333 */ + { 69, 13, 0, }, /* 334 */ + { 72, 13, 0, }, /* 335 */ + { 72, 7, 0, }, /* 336 */ + { 72, 6, 0, }, /* 337 */ + { 72, 21, 0, }, /* 338 */ + { 9, 10, 0, }, /* 339 */ + { 9, 7, 0, }, /* 340 */ + { 12, 5, 0, }, /* 341 */ + { 12, 6, 0, }, /* 342 */ + { 33, 5, 35332, }, /* 343 */ + { 33, 5, 3814, }, /* 344 */ + { 33, 5, -59, }, /* 345 */ + { 33, 9, -7615, }, /* 346 */ + { 19, 5, 8, }, /* 347 */ + { 19, 9, -8, }, /* 348 */ + { 19, 5, 74, }, /* 349 */ + { 19, 5, 86, }, /* 350 */ + { 19, 5, 100, }, /* 351 */ + { 19, 5, 128, }, /* 352 */ + { 19, 5, 112, }, /* 353 */ + { 19, 5, 126, }, /* 354 */ + { 19, 8, -8, }, /* 355 */ + { 19, 5, 9, }, /* 356 */ + { 19, 9, -74, }, /* 357 */ + { 19, 8, -9, }, /* 358 */ + { 19, 5, -7205, }, /* 359 */ + { 19, 9, -86, }, /* 360 */ + { 19, 9, -100, }, /* 361 */ + { 19, 9, -112, }, /* 362 */ + { 19, 9, -128, }, /* 363 */ + { 19, 9, -126, }, /* 364 */ + { 27, 1, 0, }, /* 365 */ + { 9, 27, 0, }, /* 366 */ + { 9, 28, 0, }, /* 367 */ + { 27, 11, 0, }, /* 368 */ + { 9, 9, 0, }, /* 369 */ + { 9, 5, 0, }, /* 370 */ + { 19, 9, -7517, }, /* 371 */ + { 33, 9, -8383, }, /* 372 */ + { 33, 9, -8262, }, /* 373 */ + { 33, 9, 28, }, /* 374 */ + { 33, 5, -28, }, /* 375 */ + { 33, 14, 16, }, /* 376 */ + { 33, 14, -16, }, /* 377 */ + { 33, 14, 0, }, /* 378 */ + { 9, 26, 26, }, /* 379 */ + { 9, 26, -26, }, /* 380 */ + { 4, 26, 0, }, /* 381 */ + { 17, 9, 48, }, /* 382 */ + { 17, 5, -48, }, /* 383 */ + { 33, 9, -10743, }, /* 384 */ + { 33, 9, -3814, }, /* 385 */ + { 33, 9, -10727, }, /* 386 */ + { 33, 5, -10795, }, /* 387 */ + { 33, 5, -10792, }, /* 388 */ + { 33, 9, -10780, }, /* 389 */ + { 33, 9, -10749, }, /* 390 */ + { 33, 9, -10783, }, /* 391 */ + { 33, 9, -10782, }, /* 392 */ + { 33, 9, -10815, }, /* 393 */ + { 10, 5, 0, }, /* 394 */ + { 10, 26, 0, }, /* 395 */ + { 10, 12, 0, }, /* 396 */ + { 10, 21, 0, }, /* 397 */ + { 10, 15, 0, }, /* 398 */ + { 16, 5, -7264, }, /* 399 */ + { 58, 7, 0, }, /* 400 */ + { 58, 6, 0, }, /* 401 */ + { 58, 21, 0, }, /* 402 */ + { 58, 12, 0, }, /* 403 */ + { 22, 26, 0, }, /* 404 */ + { 22, 6, 0, }, /* 405 */ + { 22, 14, 0, }, /* 406 */ + { 23, 12, 0, }, /* 407 */ + { 26, 7, 0, }, /* 408 */ + { 26, 6, 0, }, /* 409 */ + { 29, 7, 0, }, /* 410 */ + { 29, 6, 0, }, /* 411 */ + { 3, 7, 0, }, /* 412 */ + { 23, 26, 0, }, /* 413 */ + { 29, 26, 0, }, /* 414 */ + { 22, 7, 0, }, /* 415 */ + { 60, 7, 0, }, /* 416 */ + { 60, 6, 0, }, /* 417 */ + { 60, 26, 0, }, /* 418 */ + { 85, 7, 0, }, /* 419 */ + { 85, 6, 0, }, /* 420 */ + { 85, 21, 0, }, /* 421 */ + { 76, 7, 0, }, /* 422 */ + { 76, 6, 0, }, /* 423 */ + { 76, 21, 0, }, /* 424 */ + { 76, 13, 0, }, /* 425 */ + { 12, 7, 0, }, /* 426 */ + { 12, 21, 0, }, /* 427 */ + { 78, 7, 0, }, /* 428 */ + { 78, 14, 0, }, /* 429 */ + { 78, 12, 0, }, /* 430 */ + { 78, 21, 0, }, /* 431 */ + { 33, 9, -35332, }, /* 432 */ + { 33, 9, -42280, }, /* 433 */ + { 48, 7, 0, }, /* 434 */ + { 48, 12, 0, }, /* 435 */ + { 48, 10, 0, }, /* 436 */ + { 48, 26, 0, }, /* 437 */ + { 64, 7, 0, }, /* 438 */ + { 64, 21, 0, }, /* 439 */ + { 74, 10, 0, }, /* 440 */ + { 74, 7, 0, }, /* 441 */ + { 74, 12, 0, }, /* 442 */ + { 74, 21, 0, }, /* 443 */ + { 74, 13, 0, }, /* 444 */ + { 14, 21, 0, }, /* 445 */ + { 68, 13, 0, }, /* 446 */ + { 68, 7, 0, }, /* 447 */ + { 68, 12, 0, }, /* 448 */ + { 68, 21, 0, }, /* 449 */ + { 73, 7, 0, }, /* 450 */ + { 73, 12, 0, }, /* 451 */ + { 73, 10, 0, }, /* 452 */ + { 73, 21, 0, }, /* 453 */ + { 83, 12, 0, }, /* 454 */ + { 83, 10, 0, }, /* 455 */ + { 83, 7, 0, }, /* 456 */ + { 83, 21, 0, }, /* 457 */ + { 83, 6, 0, }, /* 458 */ + { 83, 13, 0, }, /* 459 */ + { 67, 7, 0, }, /* 460 */ + { 67, 12, 0, }, /* 461 */ + { 67, 10, 0, }, /* 462 */ + { 67, 13, 0, }, /* 463 */ + { 67, 21, 0, }, /* 464 */ + { 38, 6, 0, }, /* 465 */ + { 91, 7, 0, }, /* 466 */ + { 91, 12, 0, }, /* 467 */ + { 91, 6, 0, }, /* 468 */ + { 91, 21, 0, }, /* 469 */ + { 86, 7, 0, }, /* 470 */ + { 86, 10, 0, }, /* 471 */ + { 86, 12, 0, }, /* 472 */ + { 86, 21, 0, }, /* 473 */ + { 86, 13, 0, }, /* 474 */ + { 9, 4, 0, }, /* 475 */ + { 9, 3, 0, }, /* 476 */ + { 25, 25, 0, }, /* 477 */ + { 0, 24, 0, }, /* 478 */ + { 35, 7, 0, }, /* 479 */ + { 19, 14, 0, }, /* 480 */ + { 19, 15, 0, }, /* 481 */ + { 19, 26, 0, }, /* 482 */ + { 70, 7, 0, }, /* 483 */ + { 66, 7, 0, }, /* 484 */ + { 41, 7, 0, }, /* 485 */ + { 41, 15, 0, }, /* 486 */ + { 18, 7, 0, }, /* 487 */ + { 18, 14, 0, }, /* 488 */ + { 59, 7, 0, }, /* 489 */ + { 59, 21, 0, }, /* 490 */ + { 42, 7, 0, }, /* 491 */ + { 42, 21, 0, }, /* 492 */ + { 42, 14, 0, }, /* 493 */ + { 13, 9, 40, }, /* 494 */ + { 13, 5, -40, }, /* 495 */ + { 46, 7, 0, }, /* 496 */ + { 44, 7, 0, }, /* 497 */ + { 44, 13, 0, }, /* 498 */ + { 11, 7, 0, }, /* 499 */ + { 80, 7, 0, }, /* 500 */ + { 80, 21, 0, }, /* 501 */ + { 80, 15, 0, }, /* 502 */ + { 65, 7, 0, }, /* 503 */ + { 65, 15, 0, }, /* 504 */ + { 65, 21, 0, }, /* 505 */ + { 71, 7, 0, }, /* 506 */ + { 71, 21, 0, }, /* 507 */ + { 30, 7, 0, }, /* 508 */ + { 30, 12, 0, }, /* 509 */ + { 30, 15, 0, }, /* 510 */ + { 30, 21, 0, }, /* 511 */ + { 87, 7, 0, }, /* 512 */ + { 87, 15, 0, }, /* 513 */ + { 87, 21, 0, }, /* 514 */ + { 77, 7, 0, }, /* 515 */ + { 77, 21, 0, }, /* 516 */ + { 82, 7, 0, }, /* 517 */ + { 82, 15, 0, }, /* 518 */ + { 81, 7, 0, }, /* 519 */ + { 81, 15, 0, }, /* 520 */ + { 88, 7, 0, }, /* 521 */ + { 0, 15, 0, }, /* 522 */ + { 93, 10, 0, }, /* 523 */ + { 93, 12, 0, }, /* 524 */ + { 93, 7, 0, }, /* 525 */ + { 93, 21, 0, }, /* 526 */ + { 93, 15, 0, }, /* 527 */ + { 93, 13, 0, }, /* 528 */ + { 84, 12, 0, }, /* 529 */ + { 84, 10, 0, }, /* 530 */ + { 84, 7, 0, }, /* 531 */ + { 84, 21, 0, }, /* 532 */ + { 84, 1, 0, }, /* 533 */ + { 62, 7, 0, }, /* 534 */ + { 62, 14, 0, }, /* 535 */ + { 62, 21, 0, }, /* 536 */ + { 79, 7, 0, }, /* 537 */ + { 19, 12, 0, }, /* 538 */ + { 26, 26, 0, }, /* 539 */ +}; + +const pcre_uint8 PRIV(ucd_stage1)[] = { /* 8704 bytes */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* U+0000 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */ + 32, 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, 40, 41, 42, 43, 44, /* U+1000 */ + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, /* U+1800 */ + 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 70, 71, 72, 70, 73, 74, /* U+2000 */ + 75, 75, 65, 76, 65, 65, 77, 17, 78, 79, 80, 81, 82, 83, 84, 85, /* U+2800 */ + 86, 87, 88, 89, 90, 91, 92, 70, 93, 93, 93, 93, 93, 93, 93, 93, /* U+3000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+3800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+4000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, /* U+4800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+5000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+5800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+6000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+6800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+7000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+7800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+8000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+8800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+9000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 95, /* U+9800 */ + 96, 97, 97, 97, 97, 97, 97, 97, 97, 98, 99, 99,100,101,102,103, /* U+A000 */ +104,105,106,107,108,109,110,111, 34, 34, 34, 34, 34, 34, 34, 34, /* U+A800 */ + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B000 */ + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+B800 */ + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C000 */ + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, /* U+C800 */ + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,112, /* U+D000 */ +113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, /* U+D800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+E000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+E800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F000 */ +114,114, 93, 93,115,116,117,118,119,119,120,121,122,123,124,125, /* U+F800 */ +126,127,128,129, 17,130,131,132,133,134, 17, 17, 17, 17, 17, 17, /* U+10000 */ +135, 17,136, 17,137, 17,138, 17,139, 17, 17, 17,140, 17, 17, 17, /* U+10800 */ +141,142, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+11000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+11800 */ +143,143,143,143,143,143,144, 17,145, 17, 17, 17, 17, 17, 17, 17, /* U+12000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+12800 */ +146,146,146,146,146,146,146,146,147, 17, 17, 17, 17, 17, 17, 17, /* U+13000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+13800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+14000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+14800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+15000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+15800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+16000 */ +148,148,148,148,149, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+16800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+17000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+17800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+18000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+18800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+19000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+19800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1A800 */ +150, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1C800 */ + 70,151,152,153,154, 17,155, 17,156,157,158,159,160,161,162,163, /* U+1D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1E800 */ +164,165,166,167,168, 17,169,170,171,172,173,174,175,176,177, 17, /* U+1F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+1F800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+20000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+20800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+21000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+21800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+22000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+22800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+23000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+23800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+24000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+24800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+25000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+25800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+26000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+26800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+27000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+27800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+28000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+28800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+29000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+29800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,178, 93, 93, /* U+2A000 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, /* U+2A800 */ + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,179, 93, /* U+2B000 */ +180, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2F000 */ + 93, 93, 93, 93,180, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+2F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+30000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+30800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+31000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+31800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+32000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+32800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+33000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+33800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+34000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+34800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+35000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+35800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+36000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+36800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+37000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+37800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+38000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+38800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+39000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+39800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+3F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+40000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+40800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+41000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+41800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+42000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+42800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+43000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+43800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+44000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+44800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+45000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+45800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+46000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+46800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+47000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+47800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+48000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+48800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+49000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+49800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+4F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+50000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+50800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+51000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+51800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+52000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+52800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+53000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+53800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+54000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+54800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+55000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+55800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+56000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+56800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+57000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+57800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+58000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+58800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+59000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+59800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+5F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+60000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+60800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+61000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+61800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+62000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+62800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+63000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+63800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+64000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+64800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+65000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+65800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+66000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+66800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+67000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+67800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+68000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+68800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+69000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+69800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+6F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+70000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+70800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+71000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+71800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+72000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+72800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+73000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+73800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+74000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+74800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+75000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+75800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+76000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+76800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+77000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+77800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+78000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+78800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+79000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+79800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+7F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+80000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+80800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+81000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+81800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+82000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+82800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+83000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+83800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+84000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+84800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+85000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+85800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+86000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+86800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+87000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+87800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+88000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+88800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+89000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+89800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+8F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+90000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+90800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+91000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+91800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+92000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+92800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+93000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+93800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+94000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+94800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+95000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+95800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+96000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+96800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+97000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+97800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+98000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+98800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+99000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+99800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9A000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9A800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9B000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9B800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9C000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9C800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9D000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9D800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9E000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9E800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9F000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+9F800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A0000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A0800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A1000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A1800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A2000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A2800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A3000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A3800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A4000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A4800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A5000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A5800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A6000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A6800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A7000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A7800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A8000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A8800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A9000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+A9800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AA000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AA800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AB000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AB800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AC000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AC800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AD000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AD800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AE000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AE800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AF000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+AF800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B0000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B0800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B1000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B1800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B2000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B2800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B3000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B3800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B4000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B4800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B5000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B5800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B6000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B6800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B7000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B7800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B8000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B8800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B9000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+B9800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BA000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BA800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BB000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BB800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BC000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BC800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BD000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BD800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BE000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BE800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BF000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+BF800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C0000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C0800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C1000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C1800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C2000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C2800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C3000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C3800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C4000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C4800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C5000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C5800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C6000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C6800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C7000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C7800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C8000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C8800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C9000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+C9800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CA000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CA800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CB000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CB800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CC000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CC800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CD000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CD800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CE000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CE800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CF000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+CF800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D0000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D0800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D1000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D1800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D2000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D2800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D3000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D3800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D4000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D4800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D5000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D5800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D6000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D6800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D7000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D7800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D8000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D8800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D9000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+D9800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DA000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DA800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DB000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DB800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DC000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DC800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DD000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DD800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DE000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DE800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DF000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+DF800 */ +181, 17,182,183, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E0000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E0800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E1000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E1800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E2000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E2800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E3000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E3800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E4000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E4800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E5000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E5800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E6000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E6800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E7000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E7800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E8000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E8800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E9000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+E9800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EA000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EA800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EB000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EB800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EC000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EC800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+ED000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+ED800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EE000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EE800 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EF000 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, /* U+EF800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F0000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F0800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F1000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F1800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F2000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F2800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F3000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F3800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F4000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F4800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F5000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F5800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F6000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F6800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F7000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F7800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F8000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F8800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F9000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+F9800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FA000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FA800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FB000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FB800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FC000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FC800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FD000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FD800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FE000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FE800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+FF000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,184, /* U+FF800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+100000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+100800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+101000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+101800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+102000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+102800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+103000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+103800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+104000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+104800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+105000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+105800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+106000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+106800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+107000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+107800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+108000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+108800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+109000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+109800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10A000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10A800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10B000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10B800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10C000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10C800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10D000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10D800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10E000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10E800 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114, /* U+10F000 */ +114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,184, /* U+10F800 */ +}; + +const pcre_uint16 PRIV(ucd_stage2)[] = { /* 47360 bytes, block = 128 */ +/* block 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 2, 2, 3, 2, 2, 2, 4, 5, 2, 6, 2, 7, 2, 2, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 6, 6, 6, 2, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 2, 5, 10, 11, + 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 4, 6, 5, 6, 0, + +/* block 1 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 3, 3, 3, 13, 13, 10, 13, 14, 15, 6, 16, 13, 10, + 13, 6, 17, 17, 10, 18, 13, 2, 10, 17, 14, 19, 17, 17, 17, 2, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 6, 9, 9, 9, 9, 9, 9, 9, 14, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, 12, 12, 20, + +/* block 2 */ + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 23, 24, 21, 22, 21, 22, 21, 22, 14, 21, 22, 21, 22, 21, 22, 21, + 22, 21, 22, 21, 22, 21, 22, 21, 22, 14, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 25, 21, 22, 21, 22, 21, 22, 26, + +/* block 3 */ + 27, 28, 21, 22, 21, 22, 29, 21, 22, 30, 30, 21, 22, 14, 31, 32, + 33, 21, 22, 30, 34, 35, 36, 37, 21, 22, 38, 14, 36, 39, 40, 41, + 21, 22, 21, 22, 21, 22, 42, 21, 22, 42, 14, 14, 21, 22, 42, 21, + 22, 43, 43, 21, 22, 21, 22, 44, 21, 22, 14, 45, 21, 22, 14, 46, + 45, 45, 45, 45, 47, 48, 49, 47, 48, 49, 47, 48, 49, 21, 22, 21, + 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 50, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 14, 47, 48, 49, 21, 22, 51, 52, 21, 22, 21, 22, 21, 22, 21, 22, + +/* block 4 */ + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 53, 14, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 14, 14, 14, 14, 14, 14, 54, 21, 22, 55, 56, 57, + 57, 21, 22, 58, 59, 60, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 61, 62, 63, 64, 65, 14, 66, 66, 14, 67, 14, 68, 14, 14, 14, 14, + 66, 14, 14, 69, 14, 70, 14, 14, 71, 72, 14, 73, 14, 14, 14, 72, + 14, 74, 75, 14, 14, 76, 14, 14, 14, 14, 14, 14, 14, 77, 14, 14, + +/* block 5 */ + 78, 14, 14, 78, 14, 14, 14, 14, 78, 79, 80, 80, 81, 14, 14, 14, + 14, 14, 82, 14, 45, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 10, 10, 10, 10, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 83, 83, 83, 83, 83, 10, 10, 10, 10, 10, 85, 85, 84, 10, 84, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + +/* block 6 */ + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 87, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 88, 89, 88, 89, 84, 90, 88, 89, 91, 91, 92, 93, 93, 93, 2, 91, + +/* block 7 */ + 91, 91, 91, 91, 90, 10, 94, 2, 95, 95, 95, 91, 96, 91, 97, 97, + 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 91, 99, 99, 99, 99, 99, 99, 99, 99, 99,100,101,101,101, + 98,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102, +102,102,103,102,102,102,102,102,102,102,102,102,104,105,105,106, +107,108,109,109,109,110,111,112, 88, 89, 88, 89, 88, 89, 88, 89, + 88, 89,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +115,116,117, 98,118,119,120, 88, 89,121, 88, 89, 98,122,122,122, + +/* block 8 */ +123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, + +/* block 9 */ +127,128,129,130,130, 86, 86,130,131,131,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +132,127,128,127,128,127,128,127,128,127,128,127,128,127,128,133, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, + +/* block 10 */ +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128, 91, 91, 91, 91, 91, 91, 91, 91, + 91,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134, +134,134,134,134,134,134,134, 91, 91,135,136,136,136,136,136,136, + 91,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, +137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137, + +/* block 11 */ +137,137,137,137,137,137,137,138, 91, 2,139, 91, 91, 91, 91, 91, + 91,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140, +140,140,140,140,140,140,140,140,140,140,140,140,140,140,141,140, +142,140,140,142,140,140,142,140, 91, 91, 91, 91, 91, 91, 91, 91, +143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143, +143,143,143,143,143,143,143,143,143,143,143, 91, 91, 91, 91, 91, +143,143,143,142,142, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 12 */ +144,144,144,144, 91, 91,145,145,145,146,146,147, 2,146,148,148, +149,149,149,149,149,149,149,149,149,149,149, 2, 91, 91,146, 2, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + 84,150,150,150,150,150,150,150,150,150,150, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86,149,149,149,149,149,149,149,149,149, 86, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,146,146,146,146,150,150, + 86,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 13 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,146,150,149,149,149,149,149,149,149, 16,148,149, +149,149,149,149,149,151,151,149,149,148,149,149,149,149,150,150, +152,152,152,152,152,152,152,152,152,152,150,150,150,148,148,150, + +/* block 14 */ +153,153,153,153,153,153,153,153,153,153,153,153,153,153, 91,154, +155,156,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155, +156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156, +156,156,156,156,156,156,156,156,156,156,156, 91, 91,155,155,155, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 15 */ +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157, +157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158, +158,157, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +159,159,159,159,159,159,159,159,159,159,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160, +160,160,160,160,160,160,160,160,160,160,160,161,161,161,161,161, +161,161,161,161,162,162,163,164,164,164,162, 91, 91, 91, 91, 91, + +/* block 16 */ +165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165, +165,165,165,165,165,165,166,166,166,166,167,166,166,166,166,166, +166,166,166,166,167,166,166,166,167,166,166,166,166,166, 91, 91, +168,168,168,168,168,168,168,168,168,168,168,168,168,168,168, 91, +169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169, +169,169,169,169,169,169,169,169,169,170,170,170, 91, 91,171, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 17 */ + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 18 */ +172,172,172,173,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174, +174,174,174,174,174,174,174,174,174,174,172,173,172,174,173,173, +173,172,172,172,172,172,172,172,172,173,173,173,173,172,173,173, +174, 86, 86,172,172,172,172,172,174,174,174,174,174,174,174,174, +174,174,172,172, 2, 2,175,175,175,175,175,175,175,175,175,175, + 2,176,174,174,174,174,174,174, 91,174,174,174,174,174,174,174, + +/* block 19 */ + 91,177,178,178, 91,179,179,179,179,179,179,179,179, 91, 91,179, +179, 91, 91,179,179,179,179,179,179,179,179,179,179,179,179,179, +179,179,179,179,179,179,179,179,179, 91,179,179,179,179,179,179, +179, 91,179, 91, 91, 91,179,179,179,179, 91, 91,177,179,178,178, +178,177,177,177,177, 91, 91,178,178, 91, 91,178,178,177,179, 91, + 91, 91, 91, 91, 91, 91, 91,178, 91, 91, 91, 91,179,179, 91,179, +179,179,177,177, 91, 91,180,180,180,180,180,180,180,180,180,180, +179,179,181,181,182,182,182,182,182,182,183,181, 91, 91, 91, 91, + +/* block 20 */ + 91,184,184,185, 91,186,186,186,186,186,186, 91, 91, 91, 91,186, +186, 91, 91,186,186,186,186,186,186,186,186,186,186,186,186,186, +186,186,186,186,186,186,186,186,186, 91,186,186,186,186,186,186, +186, 91,186,186, 91,186,186, 91,186,186, 91, 91,184, 91,185,185, +185,184,184, 91, 91, 91, 91,184,184, 91, 91,184,184,184, 91, 91, + 91,184, 91, 91, 91, 91, 91, 91, 91,186,186,186,186, 91,186, 91, + 91, 91, 91, 91, 91, 91,187,187,187,187,187,187,187,187,187,187, +184,184,186,186,186,184, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 21 */ + 91,188,188,189, 91,190,190,190,190,190,190,190,190,190, 91,190, +190,190, 91,190,190,190,190,190,190,190,190,190,190,190,190,190, +190,190,190,190,190,190,190,190,190, 91,190,190,190,190,190,190, +190, 91,190,190, 91,190,190,190,190,190, 91, 91,188,190,189,189, +189,188,188,188,188,188, 91,188,188,189, 91,189,189,188, 91, 91, +190, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +190,190,188,188, 91, 91,191,191,191,191,191,191,191,191,191,191, + 91,192, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 22 */ + 91,193,194,194, 91,195,195,195,195,195,195,195,195, 91, 91,195, +195, 91, 91,195,195,195,195,195,195,195,195,195,195,195,195,195, +195,195,195,195,195,195,195,195,195, 91,195,195,195,195,195,195, +195, 91,195,195, 91,195,195,195,195,195, 91, 91,193,195,194,193, +194,193,193,193,193, 91, 91,194,194, 91, 91,194,194,193, 91, 91, + 91, 91, 91, 91, 91, 91,193,194, 91, 91, 91, 91,195,195, 91,195, +195,195,193,193, 91, 91,196,196,196,196,196,196,196,196,196,196, +197,195,198,198,198,198,198,198, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 23 */ + 91, 91,199,200, 91,200,200,200,200,200,200, 91, 91, 91,200,200, +200, 91,200,200,200,200, 91, 91, 91,200,200, 91,200, 91,200,200, + 91, 91, 91,200,200, 91, 91, 91,200,200,200, 91, 91, 91,200,200, +200,200,200,200,200,200,200,200,200,200, 91, 91, 91, 91,201,201, +199,201,201, 91, 91, 91,201,201,201, 91,201,201,201,199, 91, 91, +200, 91, 91, 91, 91, 91, 91,201, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91,202,202,202,202,202,202,202,202,202,202, +203,203,203,204,204,204,204,204,204,205,204, 91, 91, 91, 91, 91, + +/* block 24 */ + 91,206,206,206, 91,207,207,207,207,207,207,207,207, 91,207,207, +207, 91,207,207,207,207,207,207,207,207,207,207,207,207,207,207, +207,207,207,207,207,207,207,207,207, 91,207,207,207,207,207,207, +207,207,207,207, 91,207,207,207,207,207, 91, 91, 91,207,208,208, +208,206,206,206,206, 91,208,208,208, 91,208,208,208,208, 91, 91, + 91, 91, 91, 91, 91,208,208, 91,207,207, 91, 91, 91, 91, 91, 91, +207,207,208,208, 91, 91,209,209,209,209,209,209,209,209,209,209, + 91, 91, 91, 91, 91, 91, 91, 91,210,210,210,210,210,210,210,211, + +/* block 25 */ + 91, 91,212,212, 91,213,213,213,213,213,213,213,213, 91,213,213, +213, 91,213,213,213,213,213,213,213,213,213,213,213,213,213,213, +213,213,213,213,213,213,213,213,213, 91,213,213,213,213,213,213, +213,213,213,213, 91,213,213,213,213,213, 91, 91,214,213,212,214, +212,212,212,212,212, 91,214,212,212, 91,212,212,214,214, 91, 91, + 91, 91, 91, 91, 91,212,212, 91, 91, 91, 91, 91, 91, 91,213, 91, +213,213,214,214, 91, 91,215,215,215,215,215,215,215,215,215,215, + 91,213,213, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 26 */ + 91, 91,216,216, 91,217,217,217,217,217,217,217,217, 91,217,217, +217, 91,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217, +217,217,217,217,217,217,217,217,217,217,217, 91, 91,217,216,216, +216,218,218,218,218, 91,216,216,216, 91,216,216,216,218,217, 91, + 91, 91, 91, 91, 91, 91, 91,216, 91, 91, 91, 91, 91, 91, 91, 91, +217,217,218,218, 91, 91,219,219,219,219,219,219,219,219,219,219, +220,220,220,220,220,220, 91, 91, 91,221,217,217,217,217,217,217, + +/* block 27 */ + 91, 91,222,222, 91,223,223,223,223,223,223,223,223,223,223,223, +223,223,223,223,223,223,223, 91, 91, 91,223,223,223,223,223,223, +223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +223,223, 91,223,223,223,223,223,223,223,223,223, 91,223, 91, 91, +223,223,223,223,223,223,223, 91, 91, 91,224, 91, 91, 91, 91,222, +222,222,224,224,224, 91,224, 91,222,222,222,222,222,222,222,222, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91,222,222,225, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 28 */ + 91,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226, +226,227,226,226,227,227,227,227,227,227,227, 91, 91, 91, 91, 3, +226,226,226,226,226,226,228,227,227,227,227,227,227,227,227,229, +230,230,230,230,230,230,230,230,230,230,229,229, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 29 */ + 91,231,231, 91,231, 91, 91,231,231, 91,231, 91, 91,231, 91, 91, + 91, 91, 91, 91,231,231,231,231, 91,231,231,231,231,231,231,231, + 91,231,231,231, 91,231, 91,231, 91, 91,231,231, 91,231,231,231, +231,232,231,231,232,232,232,232,232,232, 91,232,232,231, 91, 91, +231,231,231,231,231, 91,233, 91,232,232,232,232,232,232, 91, 91, +234,234,234,234,234,234,234,234,234,234, 91, 91,231,231, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 30 */ +235,236,236,236,237,237,237,237,237,237,237,237,237,237,237,237, +237,237,237,236,236,236,236,236,238,238,236,236,236,236,236,236, +239,239,239,239,239,239,239,239,239,239,240,240,240,240,240,240, +240,240,240,240,236,238,236,238,236,238,241,242,241,242,243,243, +235,235,235,235,235,235,235,235, 91,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235, 91, 91, 91, + 91,238,238,238,238,238,238,238,238,238,238,238,238,238,238,243, + +/* block 31 */ +238,238,238,238,238,237,238,238,235,235,235,235,235,238,238,238, +238,238,238,238,238,238,238,238, 91,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238, 91,236,236, +236,236,236,236,236,236,238,236,236,236,236,236,236, 91,236,236, +237,237,237,237,237, 13, 13, 13, 13,237,237, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 32 */ +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,244,244,244,244,244,245,245,246,246,246, +246,245,246,246,246,246,246,246,245,246,246,245,245,246,246,244, +247,247,247,247,247,247,247,247,247,247,248,248,248,248,248,248, +244,244,244,244,244,244,245,245,246,246,244,244,244,244,246,246, +246,244,245,245,245,244,244,245,245,245,245,245,245,245,244,244, +244,246,246,246,246,244,244,244,244,244,244,244,244,244,244,244, + +/* block 33 */ +244,244,246,245,245,246,246,245,245,245,245,245,245,246,244,245, +247,247,247,247,247,247,247,247,247,247,245,245,245,246,249,249, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250, +250,250,250,250,250,250, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,251,251,251,251,251,251,251,251,251,251, 2,252, 91, 91, 91, + +/* block 34 */ +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, + +/* block 35 */ +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254, 91,254,254,254,254, 91, 91, +254,254,254,254,254,254,254, 91,254, 91,254,254,254,254, 91, 91, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + +/* block 36 */ +254,254,254,254,254,254,254,254,254, 91,254,254,254,254, 91, 91, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254, 91, +254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, + +/* block 37 */ +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254, 91,254,254,254,254, 91, 91,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254,254,254,254,254, 91, 91,255,255,255, +256,257,257,257,257,257,257,257,257,258,258,258,258,258,258,258, +258,258,258,258,258,258,258,258,258,258,258,258,258, 91, 91, 91, + +/* block 38 */ +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +256,256,256,256,256,256,256,256,256,256, 91, 91, 91, 91, 91, 91, +259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259, +259,259,259,259,259, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 39 */ +260,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, + +/* block 40 */ +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, + +/* block 41 */ +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,262,262,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, + +/* block 42 */ +263,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264, +264,264,264,264,264,264,264,264,264,264,264,265,266, 91, 91, 91, +267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267, +267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267, +267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267, +267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267, +267,267,267,267,267,267,267,267,267,267,267, 2, 2, 2,268,268, +268, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 43 */ +269,269,269,269,269,269,269,269,269,269,269,269,269, 91,269,269, +269,269,270,270,270, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, +271,271,272,272,272, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, +273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273, +273,273,274,274, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +275,275,275,275,275,275,275,275,275,275,275,275,275, 91,275,275, +275, 91,276,276, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 44 */ +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, +277,277,277,277,278,278,279,280,280,280,280,280,280,280,279,279, +279,279,279,279,279,279,280,279,279,280,280,280,280,280,280,280, +280,280,280,280,281,281,281,282,281,281,281,283,277,280, 91, 91, +284,284,284,284,284,284,284,284,284,284, 91, 91, 91, 91, 91, 91, +285,285,285,285,285,285,285,285,285,285, 91, 91, 91, 91, 91, 91, + +/* block 45 */ +286,286, 2, 2,286, 2,287,286,286,286,286,288,288,288,289, 91, +290,290,290,290,290,290,290,290,290,290, 91, 91, 91, 91, 91, 91, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,292,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 46 */ +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291, +291,291,291,291,291,291,291,291,291,288,291, 91, 91, 91, 91, 91, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 47 */ +293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293, +293,293,293,293,293,293,293,293,293,293,293,293,293, 91, 91, 91, +294,294,294,295,295,295,295,294,294,295,295,295, 91, 91, 91, 91, +295,295,294,295,295,295,295,295,295,294,294,294, 91, 91, 91, 91, +296, 91, 91, 91,297,297,298,298,298,298,298,298,298,298,298,298, +299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299, +299,299,299,299,299,299,299,299,299,299,299,299,299,299, 91, 91, +299,299,299,299,299, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 48 */ +300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300, +300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300, +300,300,300,300,300,300,300,300,300,300,300,300, 91, 91, 91, 91, +301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301, +301,300,300,300,300,300,300,300,301,301, 91, 91, 91, 91, 91, 91, +302,302,302,302,302,302,302,302,302,302,303, 91, 91, 91,304,304, +305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, +305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305, + +/* block 49 */ +306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306, +306,306,306,306,306,306,306,307,307,308,308,308, 91, 91,309,309, +310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, +310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, +310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310, +310,310,310,310,310,311,312,311,312,312,312,312,312,312,312, 91, +312,311,312,311,311,312,312,312,312,312,312,312,312,311,311,311, +311,311,311,312,312,312,312,312,312,312,312,312,312, 91, 91,312, + +/* block 50 */ +313,313,313,313,313,313,313,313,313,313, 91, 91, 91, 91, 91, 91, +313,313,313,313,313,313,313,313,313,313, 91, 91, 91, 91, 91, 91, +314,314,314,314,314,314,314,315,314,314,314,314,314,314, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 51 */ +316,316,316,316,317,318,318,318,318,318,318,318,318,318,318,318, +318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, +318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318, +318,318,318,318,316,317,316,316,316,316,316,317,316,317,317,317, +317,317,316,317,317,318,318,318,318,318,318,318, 91, 91, 91, 91, +319,319,319,319,319,319,319,319,319,319,320,320,320,320,320,320, +320,321,321,321,321,321,321,321,321,321,321,316,316,316,316,316, +316,316,316,316,321,321,321,321,321,321,321,321,321, 91, 91, 91, + +/* block 52 */ +322,322,323,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,323,322,322,322,322,323,323,322,322,323, 91, 91, 91,324,324, +325,325,325,325,325,325,325,325,325,325, 91, 91, 91, 91, 91, 91, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326, +326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326, +326,326,326,326,326,326,327,328,327,327,328,328,328,327,328,327, +327,327,328,328, 91, 91, 91, 91, 91, 91, 91, 91,329,329,329,329, + +/* block 53 */ +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,331,331,331,331,331,331,331,331,332,332,332,332, +332,332,332,332,331,331,332,332, 91, 91, 91,333,333,333,333,333, +334,334,334,334,334,334,334,334,334,334, 91, 91, 91,330,330,330, +335,335,335,335,335,335,335,335,335,335,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, +336,336,336,336,336,336,336,336,337,337,337,337,337,337,338,338, + +/* block 54 */ + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 86, 86, 86, 2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86,339, 86, 86, 86, 86, 86, 86, 86,340,340,340,340, 86,340,340, +340,340,339, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 55 */ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 98, 98, 98, 98, 98,341, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 92, 92, 92, + 92, 92, 14, 14, 14, 14, 98, 98, 98, 98, 98, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14,342,343, 14, 14, 14,344, 14, 14, + +/* block 56 */ + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 92, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 86, 86, 86, 86, + +/* block 57 */ + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + +/* block 58 */ + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 14, 14, 14, 14, 14,345, 14, 14,346, 14, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + +/* block 59 */ +347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348, +347,347,347,347,347,347, 91, 91,348,348,348,348,348,348, 91, 91, +347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348, +347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348, +347,347,347,347,347,347, 91, 91,348,348,348,348,348,348, 91, 91, + 98,347, 98,347, 98,347, 98,347, 91,348, 91,348, 91,348, 91,348, +347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348, +349,349,350,350,350,350,351,351,352,352,353,353,354,354, 91, 91, + +/* block 60 */ +347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355, +347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355, +347,347,347,347,347,347,347,347,355,355,355,355,355,355,355,355, +347,347, 98,356, 98, 91, 98, 98,348,348,357,357,358, 90,359, 90, + 90, 90, 98,356, 98, 91, 98, 98,360,360,360,360,358, 90, 90, 90, +347,347, 98, 98, 91, 91, 98, 98,348,348,361,361, 91, 90, 90, 90, +347,347, 98, 98, 98,117, 98, 98,348,348,362,362,121, 90, 90, 90, + 91, 91, 98,356, 98, 91, 98, 98,363,363,364,364,358, 90, 90, 91, + +/* block 61 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16,365,365, 16, 16, + 7, 7, 7, 7, 7, 7, 2, 2, 15, 19, 4, 15, 15, 19, 4, 15, + 2, 2, 2, 2, 2, 2, 2, 2,366,367, 16, 16, 16, 16, 16, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 19, 2, 2, 2, 2, 11, + 11, 2, 2, 2, 6, 4, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 6, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 16, 16, 16, 16, 16, 91, 91, 91, 91, 91, 16, 16, 16, 16, 16, 16, + 17, 83, 91, 91, 17, 17, 17, 17, 17, 17, 6, 6, 6, 4, 5, 83, + +/* block 62 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 6, 6, 6, 4, 5, 91, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 91, 91, 91, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,368,368,368, +368, 86,368,368,368, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 63 */ + 13, 13,369, 13, 13, 13, 13,369, 13, 13,370,369,369,369,370,370, +369,369,369,370, 13,369, 13, 13, 6,369,369,369,369,369, 13, 13, + 13, 13, 13, 13,369, 13,371, 13,369, 13,372,373,369,369, 13,370, +369,369,374,369,370,340,340,340,340,370, 13, 13,370,370,369,369, + 6, 6, 6, 6, 6,369,370,370,370,370, 13, 6, 13, 13,375, 13, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, +376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, +377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377, + +/* block 64 */ +378,378,378, 21, 22,378,378,378,378, 17, 91, 91, 91, 91, 91, 91, + 6, 6, 6, 6, 6, 13, 13, 13, 13, 13, 6, 6, 13, 13, 13, 13, + 6, 13, 13, 6, 13, 13, 6, 13, 13, 13, 13, 13, 13, 13, 6, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 6, 6, + 13, 13, 6, 13, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + +/* block 65 */ + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + +/* block 66 */ + 13, 13, 13, 13, 13, 13, 13, 13, 6, 6, 6, 6, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 6, 6, 13, 13, 13, 13, 13, 13, 13, 4, 5, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 6, 13, 13, 13, + +/* block 67 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 6, 6, 6, 6, + 6, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 68 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + +/* block 69 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13,379,379,379,379,379,379,379,379,379,379, +379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, +380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, +380,380,380,380,380,380,380,380,380,380, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + +/* block 70 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 71 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 6, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 6, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 6, 6, 6, 6, 6, 6, 6, 6, + +/* block 72 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 6, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 73 */ + 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 4, 5, 4, 5, 4, 5, 4, 5, + 4, 5, 4, 5, 4, 5, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + +/* block 74 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 6, 6, 6, 6, 6, 4, 5, 6, 6, 6, 6, 91, 6, 91, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + +/* block 75 */ +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, +381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381, + +/* block 76 */ + 6, 6, 6, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, + 5, 4, 5, 4, 5, 4, 5, 4, 5, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 4, 5, 4, 5, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 5, 6, 6, + +/* block 77 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 13, 13, 6, 6, 6, 6, 6, 6, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 78 */ +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, 91, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, +383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, 91, + 21, 22,384,385,386,387,388, 21, 22, 21, 22, 21, 22,389,390,391, +392, 14, 21, 22, 14, 21, 22, 14, 14, 14, 14, 14, 14, 83,393,393, + +/* block 79 */ +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,113,114,113,114,113,114,113,114,113,114,113,114, +113,114,113,114,394,395,395,395,395,395,395,113,114,113,114,396, +396,396, 91, 91, 91, 91, 91, 91, 91,397,397,397,397,398,397,397, + +/* block 80 */ +399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399, +399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399, +399,399,399,399,399,399, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400, 91, 91, 91, 91, 91, 91, 91, 91, 91,401, +402, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,403, + +/* block 81 */ +254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +254,254,254,254,254,254,254, 91, 91, 91, 91, 91, 91, 91, 91, 91, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, +130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130, + +/* block 82 */ + 2, 2, 15, 19, 15, 19, 2, 2, 2, 15, 19, 2, 15, 19, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 7, 2, 2, 7, 2, 15, 19, 2, 2, + 15, 19, 4, 5, 4, 5, 4, 5, 4, 5, 2, 2, 2, 2, 2, 84, + 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 83 */ +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404, 91,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 84 */ +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, + +/* block 85 */ +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404, +404,404,404,404,404,404, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, + +/* block 86 */ + 1, 2, 2, 2, 13,405,340,406, 4, 5, 4, 5, 4, 5, 4, 5, + 4, 5, 13, 13, 4, 5, 4, 5, 4, 5, 4, 5, 7, 4, 5, 5, + 13,406,406,406,406,406,406,406,406,406, 86, 86, 86, 86,407,407, + 7, 84, 84, 84, 84, 84, 13, 13,406,406,406,405,340, 2, 13, 13, + 91,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, + +/* block 87 */ +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408, 91, 91, 86, 86, 10, 10,409,409,408, + 7,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410, 2, 84,411,411,410, + +/* block 88 */ + 91, 91, 91, 91, 91,412,412,412,412,412,412,412,412,412,412,412, +412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +412,412,412,412,412,412,412,412,412,412,412,412,412,412, 91, 91, + 91,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, + +/* block 89 */ +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, 91, + 13, 13, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412, +412,412,412,412,412,412,412,412,412,412,412, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, + +/* block 90 */ +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 91, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, 13, + +/* block 91 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, 91, + +/* block 92 */ +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,414, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 93 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, + +/* block 94 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 95 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 96 */ +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,417,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, + +/* block 97 */ +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, +416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416, + +/* block 98 */ +416,416,416,416,416,416,416,416,416,416,416,416,416, 91, 91, 91, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,418,418, 91, 91, 91, 91, 91, 91, 91, 91, 91, +419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, +419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, +419,419,419,419,419,419,419,419,420,420,420,420,420,420,421,421, + +/* block 99 */ +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, + +/* block 100 */ +422,422,422,422,422,422,422,422,422,422,422,422,423,424,424,424, +422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422, +425,425,425,425,425,425,425,425,425,425,422,422, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128,127,128,127,128,127,128,426,130, +131,131,131,427, 91, 91, 91, 91, 91, 91, 91, 91,130,130,427,342, + +/* block 101 */ +127,128,127,128,127,128,127,128,127,128,127,128,127,128,127,128, +127,128,127,128,127,128,127,128, 91, 91, 91, 91, 91, 91, 91, 91, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,429,429,429,429,429,429,429,429,429,429, +430,430,431,431,431,431,431,431, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 102 */ + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 10, 10, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 14, 14, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, + 83, 14, 14, 14, 14, 14, 14, 14, 14, 21, 22, 21, 22,432, 21, 22, + +/* block 103 */ + 21, 22, 21, 22, 21, 22, 21, 22, 84, 10, 10, 21, 22,433, 14, 91, + 21, 22, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 21, 22, 21, 22, 21, 22, 21, 22, 21, 22, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 14, 45, 45, 45, 45, 45, + +/* block 104 */ +434,434,435,434,434,434,435,434,434,434,434,435,434,434,434,434, +434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434, +434,434,434,436,436,435,435,436,437,437,437,437, 91, 91, 91, 91, + 17, 17, 17, 17, 17, 17, 13, 13, 3, 13, 91, 91, 91, 91, 91, 91, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, +438,438,438,438,439,439,439,439, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 105 */ +440,440,441,441,441,441,441,441,441,441,441,441,441,441,441,441, +441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, +441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, +441,441,441,441,440,440,440,440,440,440,440,440,440,440,440,440, +440,440,440,440,442, 91, 91, 91, 91, 91, 91, 91, 91, 91,443,443, +444,444,444,444,444,444,444,444,444,444, 91, 91, 91, 91, 91, 91, +172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172, +172,172,174,174,174,174,174,174,445,445,445,174, 91, 91, 91, 91, + +/* block 106 */ +446,446,446,446,446,446,446,446,446,446,447,447,447,447,447,447, +447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, +447,447,447,447,447,447,448,448,448,448,448,448,448,448,449,449, +450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450, +450,450,450,450,450,450,450,451,451,451,451,451,451,451,451,451, +451,451,452,452, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,453, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253, 91, 91, 91, + +/* block 107 */ +454,454,454,455,456,456,456,456,456,456,456,456,456,456,456,456, +456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, +456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456, +456,456,456,454,455,455,454,454,454,454,455,455,454,455,455,455, +455,457,457,457,457,457,457,457,457,457,457,457,457,457, 91,458, +459,459,459,459,459,459,459,459,459,459, 91, 91, 91, 91,457,457, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 108 */ +460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, +460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, +460,460,460,460,460,460,460,460,460,461,461,461,461,461,461,462, +462,461,461,462,462,461,461, 91, 91, 91, 91, 91, 91, 91, 91, 91, +460,460,460,461,460,460,460,460,460,460,460,460,461,462, 91, 91, +463,463,463,463,463,463,463,463,463,463, 91, 91,464,464,464,464, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +465,244,244,244,244,244,244,249,249,249,244,245, 91, 91, 91, 91, + +/* block 109 */ +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466, +467,466,467,467,467,466,466,467,467,466,466,466,466,466,467,467, +466,467,466, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,466,466,468,469,469, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 110 */ + 91,254,254,254,254,254,254, 91, 91,254,254,254,254,254,254, 91, + 91,254,254,254,254,254,254, 91, 91, 91, 91, 91, 91, 91, 91, 91, +254,254,254,254,254,254,254, 91,254,254,254,254,254,254,254, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 111 */ + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, +470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470, +470,470,470,471,471,472,471,471,472,471,471,473,471,472, 91, 91, +474,474,474,474,474,474,474,474,474,474, 91, 91, 91, 91, 91, 91, + +/* block 112 */ +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253, 91, 91, 91, 91,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253, 91, 91, 91, 91, + +/* block 113 */ +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, +475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475, + +/* block 114 */ +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, + +/* block 115 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, + +/* block 116 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 117 */ + 14, 14, 14, 14, 14, 14, 14, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91,138,138,138,138,138, 91, 91, 91, 91, 91,143,140,143, +143,143,143,143,143,143,143,143,143,477,143,143,143,143,143,143, +143,143,143,143,143,143,143, 91,143,143,143,143,143, 91,143, 91, +143,143, 91,143,143, 91,143,143,143,143,143,143,143,143,143,143, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 118 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,478,478,478,478,478,478,478,478,478,478,478,478,478,478, +478,478, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 119 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 120 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150, 4, 5, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + +/* block 121 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, + 91, 91,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +150,150,150,150,150,150,150,150,150,150,150,150,147, 13, 91, 91, + +/* block 122 */ + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 2, 2, 2, 2, 2, 2, 2, 4, 5, 2, 91, 91, 91, 91, 91, 91, + 86, 86, 86, 86, 86, 86, 86, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 2, 7, 7, 11, 11, 4, 5, 4, 5, 4, 5, 4, 5, 4, 5, 4, + 5, 4, 5, 4, 5, 2, 2, 4, 5, 2, 2, 2, 2, 11, 11, 11, + 2, 2, 2, 91, 2, 2, 2, 2, 7, 4, 5, 4, 5, 4, 5, 2, + 2, 2, 6, 7, 6, 6, 6, 91, 2, 3, 2, 2, 91, 91, 91, 91, +150,150,150,150,150, 91,150,150,150,150,150,150,150,150,150,150, + +/* block 123 */ +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150, +150,150,150,150,150,150,150,150,150,150,150,150,150, 91, 91, 16, + +/* block 124 */ + 91, 2, 2, 2, 3, 2, 2, 2, 4, 5, 2, 6, 2, 7, 2, 2, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 2, 6, 6, 6, 2, + 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 4, 2, 5, 10, 11, + 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 4, 6, 5, 6, 4, + 5, 2, 4, 5, 2, 2,410,410,410,410,410,410,410,410,410,410, + 84,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, + +/* block 125 */ +410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, +410,410,410,410,410,410,410,410,410,410,410,410,410,410, 84, 84, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, 91, + 91, 91,253,253,253,253,253,253, 91, 91,253,253,253,253,253,253, + 91, 91,253,253,253,253,253,253, 91, 91,253,253,253, 91, 91, 91, + 3, 3, 6, 10, 13, 3, 3, 91, 13, 6, 6, 6, 6, 13, 13, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 16, 16, 16, 13, 13, 91, 91, + +/* block 126 */ +479,479,479,479,479,479,479,479,479,479,479,479, 91,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479, 91,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479, 91,479,479, 91,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479, 91, 91, +479,479,479,479,479,479,479,479,479,479,479,479,479,479, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 127 */ +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479, +479,479,479,479,479,479,479,479,479,479,479, 91, 91, 91, 91, 91, + +/* block 128 */ + 2, 2, 13, 91, 91, 91, 91, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480, +480,480,480,480,480,481,481,481,481,482,482,482,482,482,482,482, + +/* block 129 */ +482,482,482,482,482,482,482,482,482,482,481, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 86, 91, 91, + +/* block 130 */ +483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483, +483,483,483,483,483,483,483,483,483,483,483,483,483, 91, 91, 91, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484, +484, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 131 */ +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, +485,485,485,485,485,485,485,485,485,485,485,485,485,485,485, 91, +486,486,486,486, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487, +487,488,487,487,487,487,487,487,487,487,488, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 132 */ +489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489, +489,489,489,489,489,489,489,489,489,489,489,489,489,489, 91,490, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491, +491,491,491,491, 91, 91, 91, 91,491,491,491,491,491,491,491,491, +492,493,493,493,493,493, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 133 */ +494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494, +494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494, +494,494,494,494,494,494,494,494,495,495,495,495,495,495,495,495, +495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495, +495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, +496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496, + +/* block 134 */ +497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497, +497,497,497,497,497,497,497,497,497,497,497,497,497,497, 91, 91, +498,498,498,498,498,498,498,498,498,498, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 135 */ +499,499,499,499,499,499, 91, 91,499, 91,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499, +499,499,499,499,499,499, 91,499,499, 91, 91, 91,499, 91, 91,499, +500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500, +500,500,500,500,500,500, 91,501,502,502,502,502,502,502,502,502, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 136 */ +503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503, +503,503,503,503,503,503,504,504,504,504,504,504, 91, 91, 91,505, +506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506, +506,506,506,506,506,506,506,506,506,506, 91, 91, 91, 91, 91,507, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 137 */ +508,509,509,509, 91,509,509, 91, 91, 91, 91, 91,509,509,509,509, +508,508,508,508, 91,508,508,508, 91,508,508,508,508,508,508,508, +508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508, +508,508,508,508, 91, 91, 91, 91,509,509,509, 91, 91, 91, 91,509, +510,510,510,510,510,510,510,510, 91, 91, 91, 91, 91, 91, 91, 91, +511,511,511,511,511,511,511,511,511, 91, 91, 91, 91, 91, 91, 91, +512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512, +512,512,512,512,512,512,512,512,512,512,512,512,512,513,513,514, + +/* block 138 */ +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515, +515,515,515,515,515,515, 91, 91, 91,516,516,516,516,516,516,516, +517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517, +517,517,517,517,517,517, 91, 91,518,518,518,518,518,518,518,518, +519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, +519,519,519, 91, 91, 91, 91, 91,520,520,520,520,520,520,520,520, + +/* block 139 */ +521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, +521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, +521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, +521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521, +521,521,521,521,521,521,521,521,521, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 140 */ + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, +522,522,522,522,522,522,522,522,522,522,522,522,522,522,522, 91, + +/* block 141 */ +523,524,523,525,525,525,525,525,525,525,525,525,525,525,525,525, +525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, +525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525, +525,525,525,525,525,525,525,525,524,524,524,524,524,524,524,524, +524,524,524,524,524,524,524,526,526,526,526,526,526,526, 91, 91, + 91, 91,527,527,527,527,527,527,527,527,527,527,527,527,527,527, +527,527,527,527,527,527,528,528,528,528,528,528,528,528,528,528, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 142 */ +529,529,530,531,531,531,531,531,531,531,531,531,531,531,531,531, +531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, +531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531, +530,530,530,529,529,529,529,530,530,529,529,532,532,533,532,532, +532,532, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 143 */ +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, + +/* block 144 */ +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, +534,534,534,534,534,534,534,534,534,534,534,534,534,534,534, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 145 */ +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535, +535,535,535, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +536,536,536,536, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 146 */ +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, + +/* block 147 */ +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, +537,537,537,537,537,537,537,537,537,537,537,537,537,537,537, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 148 */ +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, + +/* block 149 */ +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 150 */ +410,408, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 151 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 152 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 91, 91, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13,339,339, 86, 86, 86, 13, 13, 13,339,339,339, +339,339,339, 16, 16, 16, 16, 16, 16, 16, 16, 86, 86, 86, 86, 86, + +/* block 153 */ + 86, 86, 86, 13, 13, 86, 86, 86, 86, 86, 86, 86, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 86, 86, 86, 86, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 154 */ +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482, +482,482,538,538,538,482, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 155 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 156 */ +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,370,370, +370,370,370,370,370, 91,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, + +/* block 157 */ +369,369,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,369, 91,369,369, + 91, 91,369, 91, 91,369,369, 91, 91,369,369,369,369, 91,369,369, +369,369,369,369,369,369,370,370,370,370, 91,370, 91,370,370,370, +370,370,370,370, 91,370,370,370,370,370,370,370,370,370,370,370, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + +/* block 158 */ +370,370,370,370,369,369, 91,369,369,369,369, 91, 91,369,369,369, +369,369,369,369,369, 91,369,369,369,369,369,369,369, 91,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,369,369, 91,369,369,369,369, 91, +369,369,369,369,369, 91,369, 91, 91, 91,369,369,369,369,369,369, +369, 91,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, + +/* block 159 */ +369,369,369,369,369,369,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + +/* block 160 */ +370,370,370,370,370,370,370,370,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, + +/* block 161 */ +369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370, 91, 91,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369, 6,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370, 6,370,370,370,370, +370,370,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369, 6,370,370,370,370, + +/* block 162 */ +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370, 6,370,370,370,370,370,370,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369, 6,370,370,370,370,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, 6, +370,370,370,370,370,370,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, 6, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, + +/* block 163 */ +370,370,370,370,370,370,370,370,370, 6,370,370,370,370,370,370, +369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +369,369,369,369,369,369,369,369,369, 6,370,370,370,370,370,370, +370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370, +370,370,370, 6,370,370,370,370,370,370,369,370, 91, 91, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + +/* block 164 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 165 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, + 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, + 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 166 */ + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 167 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 168 */ +539, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 169 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, + +/* block 170 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 171 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, + 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + +/* block 172 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 91, 13, 13, 13, 13, 91, 91, 91, + +/* block 173 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 174 */ + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 13, 13, 13, 13, 13, + +/* block 175 */ + 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 91, 13, 13, 13, 91, 13, 91, 13, 91, 13, 91, 13, 13, 13, 91, + 13, 13, 13, 13, 13, 13, 91, 91, 13, 13, 13, 13, 91, 13, 91, 91, + 13, 13, 13, 13, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 91, 91, 91, 91, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 176 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 177 */ + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 178 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 179 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, + +/* block 180 */ +415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, +415,415,415,415,415,415,415,415,415,415,415,415,415,415, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 181 */ + 91, 16, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + +/* block 182 */ + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + +/* block 183 */ + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + +/* block 184 */ +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476, +476,476,476,476,476,476,476,476,476,476,476,476,476,476, 91, 91, + +}; + +#if UCD_BLOCK_SIZE != 128 +#error Please correct UCD_BLOCK_SIZE in pcre_internal.h +#endif +#endif /* SUPPORT_UCP */ diff --git a/src/3rdparty/pcre/pcre_valid_utf8.c b/src/3rdparty/pcre/pcre_valid_utf8.c new file mode 100644 index 0000000000..b2dc5c9f1a --- /dev/null +++ b/src/3rdparty/pcre/pcre_valid_utf8.c @@ -0,0 +1,299 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function for validating UTF-8 character +strings. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Validate a UTF-8 string * +*************************************************/ + +/* This function is called (optionally) at the start of compile or match, to +check that a supposed UTF-8 string is actually valid. The early check means +that subsequent code can assume it is dealing with a valid string. The check +can be turned off for maximum performance, but the consequences of supplying an +invalid string are then undefined. + +Originally, this function checked according to RFC 2279, allowing for values in +the range 0 to 0x7fffffff, up to 6 bytes long, but ensuring that they were in +the canonical format. Once somebody had pointed out RFC 3629 to me (it +obsoletes 2279), additional restrictions were applied. The values are now +limited to be between 0 and 0x0010ffff, no more than 4 bytes long, and the +subrange 0xd000 to 0xdfff is excluded. However, the format of 5-byte and 6-byte +characters is still checked. + +From release 8.13 more information about the details of the error are passed +back in the returned value: + +PCRE_UTF8_ERR0 No error +PCRE_UTF8_ERR1 Missing 1 byte at the end of the string +PCRE_UTF8_ERR2 Missing 2 bytes at the end of the string +PCRE_UTF8_ERR3 Missing 3 bytes at the end of the string +PCRE_UTF8_ERR4 Missing 4 bytes at the end of the string +PCRE_UTF8_ERR5 Missing 5 bytes at the end of the string +PCRE_UTF8_ERR6 2nd-byte's two top bits are not 0x80 +PCRE_UTF8_ERR7 3rd-byte's two top bits are not 0x80 +PCRE_UTF8_ERR8 4th-byte's two top bits are not 0x80 +PCRE_UTF8_ERR9 5th-byte's two top bits are not 0x80 +PCRE_UTF8_ERR10 6th-byte's two top bits are not 0x80 +PCRE_UTF8_ERR11 5-byte character is not permitted by RFC 3629 +PCRE_UTF8_ERR12 6-byte character is not permitted by RFC 3629 +PCRE_UTF8_ERR13 4-byte character with value > 0x10ffff is not permitted +PCRE_UTF8_ERR14 3-byte character with value 0xd000-0xdfff is not permitted +PCRE_UTF8_ERR15 Overlong 2-byte sequence +PCRE_UTF8_ERR16 Overlong 3-byte sequence +PCRE_UTF8_ERR17 Overlong 4-byte sequence +PCRE_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur) +PCRE_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur) +PCRE_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character) +PCRE_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff + +Arguments: + string points to the string + length length of string, or -1 if the string is zero-terminated + errp pointer to an error position offset variable + +Returns: = 0 if the string is a valid UTF-8 string + > 0 otherwise, setting the offset of the bad character +*/ + +int +PRIV(valid_utf)(PCRE_PUCHAR string, int length, int *erroroffset) +{ +#ifdef SUPPORT_UTF +register PCRE_PUCHAR p; + +if (length < 0) + { + for (p = string; *p != 0; p++); + length = (int)(p - string); + } + +for (p = string; length-- > 0; p++) + { + register int ab, c, d; + + c = *p; + if (c < 128) continue; /* ASCII character */ + + if (c < 0xc0) /* Isolated 10xx xxxx byte */ + { + *erroroffset = (int)(p - string); + return PCRE_UTF8_ERR20; + } + + if (c >= 0xfe) /* Invalid 0xfe or 0xff bytes */ + { + *erroroffset = (int)(p - string); + return PCRE_UTF8_ERR21; + } + + ab = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */ + if (length < ab) + { + *erroroffset = (int)(p - string); /* Missing bytes */ + return ab - length; /* Codes ERR1 to ERR5 */ + } + length -= ab; /* Length remaining */ + + /* Check top bits in the second byte */ + + if (((d = *(++p)) & 0xc0) != 0x80) + { + *erroroffset = (int)(p - string) - 1; + return PCRE_UTF8_ERR6; + } + + /* For each length, check that the remaining bytes start with the 0x80 bit + set and not the 0x40 bit. Then check for an overlong sequence, and for the + excluded range 0xd800 to 0xdfff. */ + + switch (ab) + { + /* 2-byte character. No further bytes to check for 0x80. Check first byte + for for xx00 000x (overlong sequence). */ + + case 1: if ((c & 0x3e) == 0) + { + *erroroffset = (int)(p - string) - 1; + return PCRE_UTF8_ERR15; + } + break; + + /* 3-byte character. Check third byte for 0x80. Then check first 2 bytes + for 1110 0000, xx0x xxxx (overlong sequence) or + 1110 1101, 1010 xxxx (0xd800 - 0xdfff) */ + + case 2: + if ((*(++p) & 0xc0) != 0x80) /* Third byte */ + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR7; + } + if (c == 0xe0 && (d & 0x20) == 0) + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR16; + } + if (c == 0xed && d >= 0xa0) + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR14; + } + break; + + /* 4-byte character. Check 3rd and 4th bytes for 0x80. Then check first 2 + bytes for for 1111 0000, xx00 xxxx (overlong sequence), then check for a + character greater than 0x0010ffff (f4 8f bf bf) */ + + case 3: + if ((*(++p) & 0xc0) != 0x80) /* Third byte */ + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR7; + } + if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ + { + *erroroffset = (int)(p - string) - 3; + return PCRE_UTF8_ERR8; + } + if (c == 0xf0 && (d & 0x30) == 0) + { + *erroroffset = (int)(p - string) - 3; + return PCRE_UTF8_ERR17; + } + if (c > 0xf4 || (c == 0xf4 && d > 0x8f)) + { + *erroroffset = (int)(p - string) - 3; + return PCRE_UTF8_ERR13; + } + break; + + /* 5-byte and 6-byte characters are not allowed by RFC 3629, and will be + rejected by the length test below. However, we do the appropriate tests + here so that overlong sequences get diagnosed, and also in case there is + ever an option for handling these larger code points. */ + + /* 5-byte character. Check 3rd, 4th, and 5th bytes for 0x80. Then check for + 1111 1000, xx00 0xxx */ + + case 4: + if ((*(++p) & 0xc0) != 0x80) /* Third byte */ + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR7; + } + if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ + { + *erroroffset = (int)(p - string) - 3; + return PCRE_UTF8_ERR8; + } + if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ + { + *erroroffset = (int)(p - string) - 4; + return PCRE_UTF8_ERR9; + } + if (c == 0xf8 && (d & 0x38) == 0) + { + *erroroffset = (int)(p - string) - 4; + return PCRE_UTF8_ERR18; + } + break; + + /* 6-byte character. Check 3rd-6th bytes for 0x80. Then check for + 1111 1100, xx00 00xx. */ + + case 5: + if ((*(++p) & 0xc0) != 0x80) /* Third byte */ + { + *erroroffset = (int)(p - string) - 2; + return PCRE_UTF8_ERR7; + } + if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */ + { + *erroroffset = (int)(p - string) - 3; + return PCRE_UTF8_ERR8; + } + if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */ + { + *erroroffset = (int)(p - string) - 4; + return PCRE_UTF8_ERR9; + } + if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */ + { + *erroroffset = (int)(p - string) - 5; + return PCRE_UTF8_ERR10; + } + if (c == 0xfc && (d & 0x3c) == 0) + { + *erroroffset = (int)(p - string) - 5; + return PCRE_UTF8_ERR19; + } + break; + } + + /* Character is valid under RFC 2279, but 4-byte and 5-byte characters are + excluded by RFC 3629. The pointer p is currently at the last byte of the + character. */ + + if (ab > 3) + { + *erroroffset = (int)(p - string) - ab; + return (ab == 4)? PCRE_UTF8_ERR11 : PCRE_UTF8_ERR12; + } + } + +#else /* SUPPORT_UTF */ +(void)(string); /* Keep picky compilers happy */ +(void)(length); +#endif + +return PCRE_UTF8_ERR0; /* This indicates success */ +} + +/* End of pcre_valid_utf8.c */ diff --git a/src/3rdparty/pcre/pcre_version.c b/src/3rdparty/pcre/pcre_version.c new file mode 100644 index 0000000000..915ae8764c --- /dev/null +++ b/src/3rdparty/pcre/pcre_version.c @@ -0,0 +1,95 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains the external function pcre_version(), which returns a +string that identifies the PCRE version that is in use. */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Return version string * +*************************************************/ + +/* These macros are the standard way of turning unquoted text into C strings. +They allow macros like PCRE_MAJOR to be defined without quotes, which is +convenient for user programs that want to test its value. */ + +#define STRING(a) # a +#define XSTRING(s) STRING(s) + +/* A problem turned up with PCRE_PRERELEASE, which is defined empty for +production releases. Originally, it was used naively in this code: + + return XSTRING(PCRE_MAJOR) + "." XSTRING(PCRE_MINOR) + XSTRING(PCRE_PRERELEASE) + " " XSTRING(PCRE_DATE); + +However, when PCRE_PRERELEASE is empty, this leads to an attempted expansion of +STRING(). The C standard states: "If (before argument substitution) any +argument consists of no preprocessing tokens, the behavior is undefined." It +turns out the gcc treats this case as a single empty string - which is what we +really want - but Visual C grumbles about the lack of an argument for the +macro. Unfortunately, both are within their rights. To cope with both ways of +handling this, I had resort to some messy hackery that does a test at run time. +I could find no way of detecting that a macro is defined as an empty string at +pre-processor time. This hack uses a standard trick for avoiding calling +the STRING macro with an empty argument when doing the test. */ + +#ifdef COMPILE_PCRE8 +PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION +pcre_version(void) +#else +PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION +pcre16_version(void) +#endif +{ +return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)? + XSTRING(PCRE_MAJOR.PCRE_MINOR PCRE_DATE) : + XSTRING(PCRE_MAJOR.PCRE_MINOR) XSTRING(PCRE_PRERELEASE PCRE_DATE); +} + +/* End of pcre_version.c */ diff --git a/src/3rdparty/pcre/pcre_xclass.c b/src/3rdparty/pcre/pcre_xclass.c new file mode 100644 index 0000000000..45f1c5b152 --- /dev/null +++ b/src/3rdparty/pcre/pcre_xclass.c @@ -0,0 +1,198 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Copyright (c) 1997-2012 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +/* This module contains an internal function that is used to match an extended +class. It is used by both pcre_exec() and pcre_def_exec(). */ + + +#ifdef PCRE_HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcre_internal.h" + + +/************************************************* +* Match character against an XCLASS * +*************************************************/ + +/* This function is called to match a character against an extended class that +might contain values > 255 and/or Unicode properties. + +Arguments: + c the character + data points to the flag byte of the XCLASS data + +Returns: TRUE if character matches, else FALSE +*/ + +BOOL +PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf) +{ +int t; +BOOL negated = (*data & XCL_NOT) != 0; + +(void)utf; +#ifdef COMPILE_PCRE8 +/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */ +utf = TRUE; +#endif + +/* Character values < 256 are matched against a bitmap, if one is present. If +not, we still carry on, because there may be ranges that start below 256 in the +additional data. */ + +if (c < 256) + { + if ((*data & XCL_MAP) != 0 && + (((pcre_uint8 *)(data + 1))[c/8] & (1 << (c&7))) != 0) + return !negated; /* char found */ + } + +/* First skip the bit map if present. Then match against the list of Unicode +properties or large chars or ranges that end with a large char. We won't ever +encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */ + +if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar); + +while ((t = *data++) != XCL_END) + { + int x, y; + if (t == XCL_SINGLE) + { +#ifdef SUPPORT_UTF + if (utf) + { + GETCHARINC(x, data); /* macro generates multiple statements */ + } + else +#endif + x = *data++; + if (c == x) return !negated; + } + else if (t == XCL_RANGE) + { +#ifdef SUPPORT_UTF + if (utf) + { + GETCHARINC(x, data); /* macro generates multiple statements */ + GETCHARINC(y, data); /* macro generates multiple statements */ + } + else +#endif + { + x = *data++; + y = *data++; + } + if (c >= x && c <= y) return !negated; + } + +#ifdef SUPPORT_UCP + else /* XCL_PROP & XCL_NOTPROP */ + { + const ucd_record *prop = GET_UCD(c); + + switch(*data) + { + case PT_ANY: + if (t == XCL_PROP) return !negated; + break; + + case PT_LAMP: + if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll || + prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated; + break; + + case PT_GC: + if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP)) + return !negated; + break; + + case PT_PC: + if ((data[1] == prop->chartype) == (t == XCL_PROP)) return !negated; + break; + + case PT_SC: + if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated; + break; + + case PT_ALNUM: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP)) + return !negated; + break; + + case PT_SPACE: /* Perl space */ + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR) + == (t == XCL_PROP)) + return !negated; + break; + + case PT_PXSPACE: /* POSIX space */ + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z || + c == CHAR_HT || c == CHAR_NL || c == CHAR_VT || + c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP)) + return !negated; + break; + + case PT_WORD: + if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L || + PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE) + == (t == XCL_PROP)) + return !negated; + break; + + /* This should never occur, but compilers may mutter if there is no + default. */ + + default: + return FALSE; + } + + data += 2; + } +#endif /* SUPPORT_UCP */ + } + +return negated; /* char did not match */ +} + +/* End of pcre_xclass.c */ diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h new file mode 100644 index 0000000000..c832dfe60d --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitConfig.h @@ -0,0 +1,96 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SLJIT_CONFIG_H_ +#define _SLJIT_CONFIG_H_ + +/* --------------------------------------------------------------------- */ +/* Architecture */ +/* --------------------------------------------------------------------- */ + +/* Architecture selection */ +/* #define SLJIT_CONFIG_X86_32 1 */ +/* #define SLJIT_CONFIG_X86_64 1 */ +/* #define SLJIT_CONFIG_ARM_V5 1 */ +/* #define SLJIT_CONFIG_ARM_V7 1 */ +/* #define SLJIT_CONFIG_ARM_THUMB2 1 */ +/* #define SLJIT_CONFIG_PPC_32 1 */ +/* #define SLJIT_CONFIG_PPC_64 1 */ +/* #define SLJIT_CONFIG_MIPS_32 1 */ + +/* #define SLJIT_CONFIG_AUTO 1 */ +/* #define SLJIT_CONFIG_UNSUPPORTED 1 */ + +/* --------------------------------------------------------------------- */ +/* Utilities */ +/* --------------------------------------------------------------------- */ + +/* Useful for thread-safe compiling of global functions. */ +#ifndef SLJIT_UTIL_GLOBAL_LOCK +/* Enabled by default */ +#define SLJIT_UTIL_GLOBAL_LOCK 1 +#endif + +/* Implements a stack like data structure (by using mmap / VirtualAlloc). */ +#ifndef SLJIT_UTIL_STACK +/* Enabled by default */ +#define SLJIT_UTIL_STACK 1 +#endif + +/* --------------------------------------------------------------------- */ +/* Configuration */ +/* --------------------------------------------------------------------- */ + +/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should + define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMMOVE, and NULL. */ +#ifndef SLJIT_STD_MACROS_DEFINED +/* Disabled by default. */ +#define SLJIT_STD_MACROS_DEFINED 0 +#endif + +/* Executable code allocation: + If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should + define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */ +#ifndef SLJIT_EXECUTABLE_ALLOCATOR +/* Enabled by default. */ +#define SLJIT_EXECUTABLE_ALLOCATOR 1 +#endif + +/* Debug checks (assertions, etc.). */ +#ifndef SLJIT_DEBUG +/* Enabled by default */ +#define SLJIT_DEBUG 1 +#endif + +/* Verbose operations */ +#ifndef SLJIT_VERBOSE +/* Enabled by default */ +#define SLJIT_VERBOSE 1 +#endif + +/* See the beginning of sljitConfigInternal.h */ + +#endif diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h new file mode 100644 index 0000000000..de6e9f07e2 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h @@ -0,0 +1,424 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SLJIT_CONFIG_INTERNAL_H_ +#define _SLJIT_CONFIG_INTERNAL_H_ + +/* + SLJIT defines the following macros depending on the target architecture: + + Feature detection (boolean) macros: + SLJIT_32BIT_ARCHITECTURE : 32 bit architecture + SLJIT_64BIT_ARCHITECTURE : 64 bit architecture + SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index + SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index + SLJIT_LITTLE_ENDIAN : little endian architecture + SLJIT_BIG_ENDIAN : big endian architecture + SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!) + SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information + + Types and useful macros: + sljit_b, sljit_ub : signed and unsigned 8 bit byte + sljit_h, sljit_uh : signed and unsigned 16 bit half-word (short) type + sljit_i, sljit_ui : signed and unsigned 32 bit integer type + sljit_w, sljit_uw : signed and unsigned machine word, enough to store a pointer (same as intptr_t) + SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT + SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper) +*/ + +#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + || (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ + || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + || (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + || (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)) +#error "An architecture must be selected" +#endif + +/* Sanity check. */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ + + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 +#error "Multiple architectures are selected" +#endif + +/* Auto select option (requires compiler support) */ +#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) + +#ifndef _WIN32 + +#if defined(__i386__) || defined(__i386) +#define SLJIT_CONFIG_X86_32 1 +#elif defined(__x86_64__) +#define SLJIT_CONFIG_X86_64 1 +#elif defined(__arm__) || defined(__ARM__) +#ifdef __thumb2__ +#define SLJIT_CONFIG_ARM_THUMB2 1 +#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) +#define SLJIT_CONFIG_ARM_V7 1 +#else +#define SLJIT_CONFIG_ARM_V5 1 +#endif +#elif defined(__ppc64__) || defined(__powerpc64__) +#define SLJIT_CONFIG_PPC_64 1 +#elif defined(__ppc__) || defined(__powerpc__) +#define SLJIT_CONFIG_PPC_32 1 +#elif defined(__mips__) +#define SLJIT_CONFIG_MIPS_32 1 +#else +/* Unsupported architecture */ +#define SLJIT_CONFIG_UNSUPPORTED 1 +#endif + +#else /* !_WIN32 */ + +#if defined(_M_X64) || defined(__x86_64__) +#define SLJIT_CONFIG_X86_64 1 +#elif defined(_ARM_) +#define SLJIT_CONFIG_ARM_V5 1 +#else +#define SLJIT_CONFIG_X86_32 1 +#endif + +#endif /* !WIN32 */ +#endif /* SLJIT_CONFIG_AUTO */ + +#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +#undef SLJIT_EXECUTABLE_ALLOCATOR +#endif + +#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED) + +/* These libraries are needed for the macros below. */ +#include +#include + +#endif /* STD_MACROS_DEFINED */ + +/* General macros: + Note: SLJIT is designed to be independent from them as possible. + + In release mode (SLJIT_DEBUG is not defined) only the following macros are needed: +*/ + +#ifndef SLJIT_MALLOC +#define SLJIT_MALLOC(size) malloc(size) +#endif + +#ifndef SLJIT_FREE +#define SLJIT_FREE(ptr) free(ptr) +#endif + +#ifndef SLJIT_MEMMOVE +#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len) +#endif + +#ifndef SLJIT_ZEROMEM +#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len) +#endif + +#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) + +#if defined(__GNUC__) && (__GNUC__ >= 3) +#define SLJIT_LIKELY(x) __builtin_expect((x), 1) +#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0) +#else +#define SLJIT_LIKELY(x) (x) +#define SLJIT_UNLIKELY(x) (x) +#endif + +#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */ + +#ifndef SLJIT_INLINE +/* Inline functions. */ +#define SLJIT_INLINE __inline +#endif + +#ifndef SLJIT_CONST +/* Const variables. */ +#define SLJIT_CONST const +#endif + +#ifndef SLJIT_UNUSED_ARG +/* Unused arguments. */ +#define SLJIT_UNUSED_ARG(arg) (void)arg +#endif + +#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) +/* Static ABI functions. For all-in-one programs. */ + +#if defined(__GNUC__) +/* Disable unused warnings in gcc. */ +#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused)) +#else +#define SLJIT_API_FUNC_ATTRIBUTE static +#endif + +#else +#define SLJIT_API_FUNC_ATTRIBUTE +#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */ + +#ifndef SLJIT_CACHE_FLUSH + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + +/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */ +#define SLJIT_CACHE_FLUSH(from, to) \ + ppc_cache_flush((from), (to)) + +#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + +/* Not required to implement on archs with unified caches. */ +#define SLJIT_CACHE_FLUSH(from, to) + +#else + +/* Calls __ARM_NR_cacheflush on ARM-Linux. */ +#define SLJIT_CACHE_FLUSH(from, to) \ + __clear_cache((char*)(from), (char*)(to)) + +#endif + +#endif /* !SLJIT_CACHE_FLUSH */ + +/* 8 bit byte type. */ +typedef unsigned char sljit_ub; +typedef signed char sljit_b; + +/* 16 bit half-word type. */ +typedef unsigned short int sljit_uh; +typedef signed short int sljit_h; + +/* 32 bit integer type. */ +typedef unsigned int sljit_ui; +typedef signed int sljit_i; + +/* Machine word type. Can encapsulate a pointer. + 32 bit for 32 bit machines. + 64 bit for 64 bit machines. */ +#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) +/* Just to have something. */ +#define SLJIT_WORD_SHIFT 0 +typedef unsigned long int sljit_uw; +typedef long int sljit_w; +#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define SLJIT_32BIT_ARCHITECTURE 1 +#define SLJIT_WORD_SHIFT 2 +typedef unsigned int sljit_uw; +typedef int sljit_w; +#else +#define SLJIT_64BIT_ARCHITECTURE 1 +#define SLJIT_WORD_SHIFT 3 +#ifdef _WIN32 +typedef unsigned __int64 sljit_uw; +typedef __int64 sljit_w; +#else +typedef unsigned long int sljit_uw; +typedef long int sljit_w; +#endif +#endif + +/* Double precision. */ +#define SLJIT_FLOAT_SHIFT 3 + +#ifndef SLJIT_W + +/* Defining long constants. */ +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#define SLJIT_W(w) (w##ll) +#else +#define SLJIT_W(w) (w) +#endif + +#endif /* !SLJIT_W */ + +#ifndef SLJIT_CALL + +/* ABI (Application Binary Interface) types. */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + +#if defined(__GNUC__) + +#define SLJIT_CALL __attribute__ ((fastcall)) +#define SLJIT_X86_32_FASTCALL 1 + +#elif defined(_WIN32) + +#ifdef __BORLANDC__ +#define SLJIT_CALL __msfastcall +#else /* __BORLANDC__ */ +#define SLJIT_CALL __fastcall +#endif /* __BORLANDC__ */ +#define SLJIT_X86_32_FASTCALL 1 + +#else /* defined(_WIN32) */ +#define SLJIT_CALL __stdcall +#endif + +#else /* Other architectures. */ + +#define SLJIT_CALL + +#endif /* SLJIT_CONFIG_X86_32 */ + +#endif /* !SLJIT_CALL */ + +#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) + +/* These macros are useful for the application. */ +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define SLJIT_BIG_ENDIAN 1 + +#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + +#ifdef __MIPSEL__ +#define SLJIT_LITTLE_ENDIAN 1 +#else +#define SLJIT_BIG_ENDIAN 1 +#endif + +#else +#define SLJIT_LITTLE_ENDIAN 1 +#endif + +#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */ + +/* Sanity check. */ +#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#error "Exactly one endianness must be selected" +#endif + +#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#error "Exactly one endianness must be selected" +#endif + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +/* It seems ppc64 compilers use an indirect addressing for functions. + It makes things really complicated. */ +#define SLJIT_INDIRECT_CALL 1 +#endif + +#ifndef SLJIT_SSE2 + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +/* Turn on SSE2 support on x86 (operating on doubles). + (Better performance than legacy fpu instructions). */ +#define SLJIT_SSE2 1 + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +/* Auto detect SSE2 support using CPUID. + On 64 bit x86 cpus, sse2 must be present. */ +#define SLJIT_SSE2_AUTO 1 +#endif + +#endif /* (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) */ + +#endif /* !SLJIT_SSE2 */ + +#ifndef SLJIT_UNALIGNED + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define SLJIT_UNALIGNED 1 +#endif + +#endif /* !SLJIT_UNALIGNED */ + +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size); +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr); +#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size) +#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr) +#endif + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +#include +#endif + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + +/* Feel free to redefine these two macros. */ +#ifndef SLJIT_ASSERT + +#define SLJIT_HALT_PROCESS() \ + *((int*)0) = 0 + +#define SLJIT_ASSERT(x) \ + do { \ + if (SLJIT_UNLIKELY(!(x))) { \ + printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \ + SLJIT_HALT_PROCESS(); \ + } \ + } while (0) + +#endif /* !SLJIT_ASSERT */ + +#ifndef SLJIT_ASSERT_STOP + +#define SLJIT_ASSERT_STOP() \ + do { \ + printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \ + SLJIT_HALT_PROCESS(); \ + } while (0) + +#endif /* !SLJIT_ASSERT_STOP */ + +#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ + +#undef SLJIT_ASSERT +#undef SLJIT_ASSERT_STOP + +#define SLJIT_ASSERT(x) \ + do { } while (0) +#define SLJIT_ASSERT_STOP() \ + do { } while (0) + +#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */ + +#ifndef SLJIT_COMPILE_ASSERT + +/* Should be improved eventually. */ +#define SLJIT_COMPILE_ASSERT(x, description) \ + SLJIT_ASSERT(x) + +#endif /* !SLJIT_COMPILE_ASSERT */ + +#endif diff --git a/src/3rdparty/pcre/sljit/sljitExecAllocator.c b/src/3rdparty/pcre/sljit/sljitExecAllocator.c new file mode 100644 index 0000000000..f66744df82 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitExecAllocator.c @@ -0,0 +1,277 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file contains a simple executable memory allocator + + It is assumed, that executable code blocks are usually medium (or sometimes + large) memory blocks, and the allocator is not too frequently called (less + optimized than other allocators). Thus, using it as a generic allocator is + not suggested. + + How does it work: + Memory is allocated in continuous memory areas called chunks by alloc_chunk() + Chunk format: + [ block ][ block ] ... [ block ][ block terminator ] + + All blocks and the block terminator is started with block_header. The block + header contains the size of the previous and the next block. These sizes + can also contain special values. + Block size: + 0 - The block is a free_block, with a different size member. + 1 - The block is a block terminator. + n - The block is used at the moment, and the value contains its size. + Previous block size: + 0 - This is the first block of the memory chunk. + n - The size of the previous block. + + Using these size values we can go forward or backward on the block chain. + The unused blocks are stored in a chain list pointed by free_blocks. This + list is useful if we need to find a suitable memory area when the allocator + is called. + + When a block is freed, the new free block is connected to its adjacent free + blocks if possible. + + [ free block ][ used block ][ free block ] + and "used block" is freed, the three blocks are connected together: + [ one big free block ] +*/ + +/* --------------------------------------------------------------------- */ +/* System (OS) functions */ +/* --------------------------------------------------------------------- */ + +/* 64 KByte. */ +#define CHUNK_SIZE 0x10000 + +/* + alloc_chunk / free_chunk : + * allocate executable system memory chunks + * the size is always divisible by CHUNK_SIZE + allocator_grab_lock / allocator_release_lock : + * make the allocator thread safe + * can be empty if the OS (or the application) does not support threading + * only the allocator requires this lock, sljit is fully thread safe + as it only uses local variables +*/ + +#ifdef _WIN32 + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +} + +static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size) +{ + SLJIT_UNUSED_ARG(size); + VirtualFree(chunk, 0, MEM_RELEASE); +} + +#else + +#include + +static SLJIT_INLINE void* alloc_chunk(sljit_uw size) +{ + void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); + return (retval != MAP_FAILED) ? retval : NULL; +} + +static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size) +{ + munmap(chunk, size); +} + +#endif + +/* --------------------------------------------------------------------- */ +/* Common functions */ +/* --------------------------------------------------------------------- */ + +#define CHUNK_MASK (~(CHUNK_SIZE - 1)) + +struct block_header { + sljit_uw size; + sljit_uw prev_size; +}; + +struct free_block { + struct block_header header; + struct free_block *next; + struct free_block *prev; + sljit_uw size; +}; + +#define AS_BLOCK_HEADER(base, offset) \ + ((struct block_header*)(((sljit_ub*)base) + offset)) +#define AS_FREE_BLOCK(base, offset) \ + ((struct free_block*)(((sljit_ub*)base) + offset)) +#define MEM_START(base) ((void*)(((sljit_ub*)base) + sizeof(struct block_header))) +#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7) + +static struct free_block* free_blocks; +static sljit_uw allocated_size; +static sljit_uw total_size; + +static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size) +{ + free_block->header.size = 0; + free_block->size = size; + + free_block->next = free_blocks; + free_block->prev = 0; + if (free_blocks) + free_blocks->prev = free_block; + free_blocks = free_block; +} + +static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block) +{ + if (free_block->next) + free_block->next->prev = free_block->prev; + + if (free_block->prev) + free_block->prev->next = free_block->next; + else { + SLJIT_ASSERT(free_blocks == free_block); + free_blocks = free_block->next; + } +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ + struct block_header *header; + struct block_header *next_header; + struct free_block *free_block; + sljit_uw chunk_size; + + allocator_grab_lock(); + if (size < sizeof(struct free_block)) + size = sizeof(struct free_block); + size = ALIGN_SIZE(size); + + free_block = free_blocks; + while (free_block) { + if (free_block->size >= size) { + chunk_size = free_block->size; + if (chunk_size > size + 64) { + /* We just cut a block from the end of the free block. */ + chunk_size -= size; + free_block->size = chunk_size; + header = AS_BLOCK_HEADER(free_block, chunk_size); + header->prev_size = chunk_size; + AS_BLOCK_HEADER(header, size)->prev_size = size; + } + else { + sljit_remove_free_block(free_block); + header = (struct block_header*)free_block; + size = chunk_size; + } + allocated_size += size; + header->size = size; + allocator_release_lock(); + return MEM_START(header); + } + free_block = free_block->next; + } + + chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK; + header = (struct block_header*)alloc_chunk(chunk_size); + PTR_FAIL_IF(!header); + + chunk_size -= sizeof(struct block_header); + total_size += chunk_size; + + header->prev_size = 0; + if (chunk_size > size + 64) { + /* Cut the allocated space into a free and a used block. */ + allocated_size += size; + header->size = size; + chunk_size -= size; + + free_block = AS_FREE_BLOCK(header, size); + free_block->header.prev_size = size; + sljit_insert_free_block(free_block, chunk_size); + next_header = AS_BLOCK_HEADER(free_block, chunk_size); + } + else { + /* All space belongs to this allocation. */ + allocated_size += chunk_size; + header->size = chunk_size; + next_header = AS_BLOCK_HEADER(header, chunk_size); + } + next_header->size = 1; + next_header->prev_size = chunk_size; + allocator_release_lock(); + return MEM_START(header); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + struct block_header *header; + struct free_block* free_block; + + allocator_grab_lock(); + header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header)); + allocated_size -= header->size; + + /* Connecting free blocks together if possible. */ + + /* If header->prev_size == 0, free_block will equal to header. + In this case, free_block->header.size will be > 0. */ + free_block = AS_FREE_BLOCK(header, -(sljit_w)header->prev_size); + if (SLJIT_UNLIKELY(!free_block->header.size)) { + free_block->size += header->size; + header = AS_BLOCK_HEADER(free_block, free_block->size); + header->prev_size = free_block->size; + } + else { + free_block = (struct free_block*)header; + sljit_insert_free_block(free_block, header->size); + } + + header = AS_BLOCK_HEADER(free_block, free_block->size); + if (SLJIT_UNLIKELY(!header->size)) { + free_block->size += ((struct free_block*)header)->size; + sljit_remove_free_block((struct free_block*)header); + header = AS_BLOCK_HEADER(free_block, free_block->size); + header->prev_size = free_block->size; + } + + /* The whole chunk is free. */ + if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) { + /* If this block is freed, we still have (allocated_size / 2) free space. */ + if (total_size - free_block->size > (allocated_size * 3 / 2)) { + total_size -= free_block->size; + sljit_remove_free_block(free_block); + free_chunk(free_block, free_block->size + sizeof(struct block_header)); + } + } + + allocator_release_lock(); +} diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c new file mode 100644 index 0000000000..c1fa5e4af9 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitLir.c @@ -0,0 +1,1594 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "sljitLir.h" + +#define CHECK_ERROR() \ + do { \ + if (SLJIT_UNLIKELY(compiler->error)) \ + return compiler->error; \ + } while (0) + +#define CHECK_ERROR_PTR() \ + do { \ + if (SLJIT_UNLIKELY(compiler->error)) \ + return NULL; \ + } while (0) + +#define CHECK_ERROR_VOID() \ + do { \ + if (SLJIT_UNLIKELY(compiler->error)) \ + return; \ + } while (0) + +#define FAIL_IF(expr) \ + do { \ + if (SLJIT_UNLIKELY(expr)) \ + return compiler->error; \ + } while (0) + +#define PTR_FAIL_IF(expr) \ + do { \ + if (SLJIT_UNLIKELY(expr)) \ + return NULL; \ + } while (0) + +#define FAIL_IF_NULL(ptr) \ + do { \ + if (SLJIT_UNLIKELY(!(ptr))) { \ + compiler->error = SLJIT_ERR_ALLOC_FAILED; \ + return SLJIT_ERR_ALLOC_FAILED; \ + } \ + } while (0) + +#define PTR_FAIL_IF_NULL(ptr) \ + do { \ + if (SLJIT_UNLIKELY(!(ptr))) { \ + compiler->error = SLJIT_ERR_ALLOC_FAILED; \ + return NULL; \ + } \ + } while (0) + +#define PTR_FAIL_WITH_EXEC_IF(ptr) \ + do { \ + if (SLJIT_UNLIKELY(!(ptr))) { \ + compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \ + return NULL; \ + } \ + } while (0) + +#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) + +#define GET_OPCODE(op) \ + ((op) & ~(SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS)) + +#define GET_FLAGS(op) \ + ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C)) + +#define GET_ALL_FLAGS(op) \ + ((op) & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS)) + +#define BUF_SIZE 4096 + +#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) +#define ABUF_SIZE 2048 +#else +#define ABUF_SIZE 4096 +#endif + +/* Jump flags. */ +#define JUMP_LABEL 0x1 +#define JUMP_ADDR 0x2 +/* SLJIT_REWRITABLE_JUMP is 0x1000. */ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + #define PATCH_MB 0x4 + #define PATCH_MW 0x8 +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + #define PATCH_MD 0x10 +#endif +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + #define IS_BL 0x4 + #define PATCH_B 0x8 +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + #define CPOOL_SIZE 512 +#endif + +#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) + #define IS_CONDITIONAL 0x04 + #define IS_BL 0x08 + /* cannot be encoded as branch */ + #define B_TYPE0 0x00 + /* conditional + imm8 */ + #define B_TYPE1 0x10 + /* conditional + imm20 */ + #define B_TYPE2 0x20 + /* IT + imm24 */ + #define B_TYPE3 0x30 + /* imm11 */ + #define B_TYPE4 0x40 + /* imm24 */ + #define B_TYPE5 0x50 + /* BL + imm24 */ + #define BL_TYPE6 0x60 + /* 0xf00 cc code for branches */ +#endif + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + #define UNCOND_B 0x04 + #define PATCH_B 0x08 + #define ABSOLUTE_B 0x10 +#endif + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #define IS_MOVABLE 0x04 + #define IS_JAL 0x08 + #define IS_BIT26_COND 0x10 + #define IS_BIT16_COND 0x20 + + #define IS_COND (IS_BIT26_COND | IS_BIT16_COND) + + #define PATCH_B 0x40 + #define PATCH_J 0x80 + + /* instruction types */ + #define UNMOVABLE_INS 0 + /* 1 - 31 last destination register */ + #define FCSR_FCC 32 + /* no destination (i.e: store) */ + #define MOVABLE_INS 33 +#endif + +#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */ + +/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */ +#include "sljitUtils.c" + +#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) + +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +#include "sljitExecAllocator.c" +#endif + +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) && !(defined SLJIT_SSE2 && SLJIT_SSE2) +#error SLJIT_SSE2_AUTO cannot be enabled without SLJIT_SSE2 +#endif + +/* --------------------------------------------------------------------- */ +/* Public functions */ +/* --------------------------------------------------------------------- */ + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || ((defined SLJIT_SSE2 && SLJIT_SSE2) && ((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64))) +#define SLJIT_NEEDS_COMPILER_INIT 1 +static int compiler_initialized = 0; +/* A thread safe initialization. */ +static void init_compiler(void); +#endif + + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void) +{ + struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler)); + if (!compiler) + return NULL; + SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler)); + + SLJIT_COMPILE_ASSERT( + sizeof(sljit_b) == 1 && sizeof(sljit_ub) == 1 + && sizeof(sljit_h) == 2 && sizeof(sljit_uh) == 2 + && sizeof(sljit_i) == 4 && sizeof(sljit_ui) == 4 + && ((sizeof(sljit_w) == 4 && sizeof(sljit_uw) == 4) || (sizeof(sljit_w) == 8 && sizeof(sljit_uw) == 8)), + invalid_integer_types); + + /* Only the non-zero members must be set. */ + compiler->error = SLJIT_SUCCESS; + + compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE); + compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE); + + if (!compiler->buf || !compiler->abuf) { + if (compiler->buf) + SLJIT_FREE(compiler->buf); + if (compiler->abuf) + SLJIT_FREE(compiler->abuf); + SLJIT_FREE(compiler); + return NULL; + } + + compiler->buf->next = NULL; + compiler->buf->used_size = 0; + compiler->abuf->next = NULL; + compiler->abuf->used_size = 0; + + compiler->temporaries = -1; + compiler->saveds = -1; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + compiler->args = -1; +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw) + CPOOL_SIZE * sizeof(sljit_ub)); + if (!compiler->cpool) { + SLJIT_FREE(compiler->buf); + SLJIT_FREE(compiler->abuf); + SLJIT_FREE(compiler); + return NULL; + } + compiler->cpool_unique = (sljit_ub*)(compiler->cpool + CPOOL_SIZE); + compiler->cpool_diff = 0xffffffff; +#endif + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + compiler->delay_slot = UNMOVABLE_INS; +#endif + +#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT) + if (!compiler_initialized) { + init_compiler(); + compiler_initialized = 1; + } +#endif + + return compiler; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + struct sljit_memory_fragment *curr; + + buf = compiler->buf; + while (buf) { + curr = buf; + buf = buf->next; + SLJIT_FREE(curr); + } + + buf = compiler->abuf; + while (buf) { + curr = buf; + buf = buf->next; + SLJIT_FREE(curr); + } + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + SLJIT_FREE(compiler->cpool); +#endif + SLJIT_FREE(compiler); +} + +#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +{ + /* Remove thumb mode flag. */ + SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1)); +} +#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +{ + /* Resolve indirection. */ + code = (void*)(*(sljit_uw*)code); + SLJIT_FREE_EXEC(code); +} +#else +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +{ + SLJIT_FREE_EXEC(code); +} +#endif + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) +{ + if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) { + jump->flags &= ~JUMP_ADDR; + jump->flags |= JUMP_LABEL; + jump->u.label = label; + } +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) +{ + if (SLJIT_LIKELY(!!jump)) { + SLJIT_ASSERT(jump->flags & SLJIT_REWRITABLE_JUMP); + + jump->flags &= ~JUMP_LABEL; + jump->flags |= JUMP_ADDR; + jump->u.target = target; + } +} + +/* --------------------------------------------------------------------- */ +/* Private functions */ +/* --------------------------------------------------------------------- */ + +static void* ensure_buf(struct sljit_compiler *compiler, int size) +{ + sljit_ub *ret; + struct sljit_memory_fragment *new_frag; + + if (compiler->buf->used_size + size <= (int)(BUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) { + ret = compiler->buf->memory + compiler->buf->used_size; + compiler->buf->used_size += size; + return ret; + } + new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE); + PTR_FAIL_IF_NULL(new_frag); + new_frag->next = compiler->buf; + compiler->buf = new_frag; + new_frag->used_size = size; + return new_frag->memory; +} + +static void* ensure_abuf(struct sljit_compiler *compiler, int size) +{ + sljit_ub *ret; + struct sljit_memory_fragment *new_frag; + + if (compiler->abuf->used_size + size <= (int)(ABUF_SIZE - sizeof(sljit_uw) - sizeof(void*))) { + ret = compiler->abuf->memory + compiler->abuf->used_size; + compiler->abuf->used_size += size; + return ret; + } + new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE); + PTR_FAIL_IF_NULL(new_frag); + new_frag->next = compiler->abuf; + compiler->abuf = new_frag; + new_frag->used_size = size; + return new_frag->memory; +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size) +{ + CHECK_ERROR_PTR(); + +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + if (size <= 0 || size > 128) + return NULL; + size = (size + 7) & ~7; +#else + if (size <= 0 || size > 64) + return NULL; + size = (size + 3) & ~3; +#endif + return ensure_abuf(compiler, size); +} + +static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf = compiler->buf; + struct sljit_memory_fragment *prev = NULL; + struct sljit_memory_fragment *tmp; + + do { + tmp = buf->next; + buf->next = prev; + prev = buf; + buf = tmp; + } while (buf != NULL); + + compiler->buf = prev; +} + +static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler) +{ + label->next = NULL; + label->size = compiler->size; + if (compiler->last_label) + compiler->last_label->next = label; + else + compiler->labels = label; + compiler->last_label = label; +} + +static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, int flags) +{ + jump->next = NULL; + jump->flags = flags; + if (compiler->last_jump) + compiler->last_jump->next = jump; + else + compiler->jumps = jump; + compiler->last_jump = jump; +} + +static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler) +{ + const_->next = NULL; + const_->addr = compiler->size; + if (compiler->last_const) + compiler->last_const->next = const_; + else + compiler->consts = const_; + compiler->last_const = const_; +} + +#define ADDRESSING_DEPENDS_ON(exp, reg) \ + (((exp) & SLJIT_MEM) && (((exp) & 0xf) == reg || (((exp) >> 4) & 0xf) == reg)) + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) +#define FUNCTION_CHECK_OP() \ + SLJIT_ASSERT(!GET_FLAGS(op) || !(op & SLJIT_KEEP_FLAGS)); \ + switch (GET_OPCODE(op)) { \ + case SLJIT_NOT: \ + case SLJIT_CLZ: \ + case SLJIT_AND: \ + case SLJIT_OR: \ + case SLJIT_XOR: \ + case SLJIT_SHL: \ + case SLJIT_LSHR: \ + case SLJIT_ASHR: \ + SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C))); \ + break; \ + case SLJIT_NEG: \ + SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \ + break; \ + case SLJIT_MUL: \ + SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))); \ + break; \ + case SLJIT_FCMP: \ + SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ + SLJIT_ASSERT((op & (SLJIT_SET_E | SLJIT_SET_S))); \ + break; \ + case SLJIT_ADD: \ + SLJIT_ASSERT(!(op & (SLJIT_SET_S | SLJIT_SET_U))); \ + break; \ + case SLJIT_SUB: \ + break; \ + case SLJIT_ADDC: \ + case SLJIT_SUBC: \ + SLJIT_ASSERT(!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))); \ + break; \ + default: \ + /* Nothing allowed */ \ + SLJIT_ASSERT(!(op & (SLJIT_INT_OP | SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O | SLJIT_SET_C | SLJIT_KEEP_FLAGS))); \ + break; \ + } + +#define FUNCTION_CHECK_IS_REG(r) \ + ((r) == SLJIT_UNUSED || (r) == SLJIT_LOCALS_REG || \ + ((r) >= SLJIT_TEMPORARY_REG1 && (r) <= SLJIT_TEMPORARY_REG3 && (r) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \ + ((r) >= SLJIT_SAVED_REG1 && (r) <= SLJIT_SAVED_REG3 && (r) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds)) \ + +#define FUNCTION_CHECK_SRC(p, i) \ + SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \ + if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \ + ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \ + (p) == SLJIT_LOCALS_REG) \ + SLJIT_ASSERT(i == 0); \ + else if ((p) == SLJIT_IMM) \ + ; \ + else if ((p) & SLJIT_MEM) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \ + if ((p) & 0xf0) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \ + SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \ + } else \ + SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \ + SLJIT_ASSERT(((p) >> 9) == 0); \ + } \ + else \ + SLJIT_ASSERT_STOP(); + +#define FUNCTION_CHECK_DST(p, i) \ + SLJIT_ASSERT(compiler->temporaries != -1 && compiler->saveds != -1); \ + if (((p) >= SLJIT_TEMPORARY_REG1 && (p) <= SLJIT_TEMPORARY_REG1 - 1 + compiler->temporaries) || \ + ((p) >= SLJIT_SAVED_REG1 && (p) <= SLJIT_SAVED_REG1 - 1 + compiler->saveds) || \ + (p) == SLJIT_UNUSED) \ + SLJIT_ASSERT(i == 0); \ + else if ((p) & SLJIT_MEM) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \ + if ((p) & 0xf0) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \ + SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \ + } else \ + SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \ + SLJIT_ASSERT(((p) >> 9) == 0); \ + } \ + else \ + SLJIT_ASSERT_STOP(); + +#define FUNCTION_FCHECK(p, i) \ + if ((p) >= SLJIT_FLOAT_REG1 && (p) <= SLJIT_FLOAT_REG4) \ + SLJIT_ASSERT(i == 0); \ + else if ((p) & SLJIT_MEM) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG((p) & 0xf)); \ + if ((p) & 0xf0) { \ + SLJIT_ASSERT(FUNCTION_CHECK_IS_REG(((p) >> 4) & 0xf)); \ + SLJIT_ASSERT(((p) & 0xf0) != (SLJIT_LOCALS_REG << 4) && !(i & ~0x3)); \ + } else \ + SLJIT_ASSERT((((p) >> 4) & 0xf) == 0); \ + SLJIT_ASSERT(((p) >> 9) == 0); \ + } \ + else \ + SLJIT_ASSERT_STOP(); + +#define FUNCTION_CHECK_OP1() \ + if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \ + SLJIT_ASSERT(!GET_ALL_FLAGS(op)); \ + } \ + if (GET_OPCODE(op) >= SLJIT_MOVU && GET_OPCODE(op) <= SLJIT_MOVU_SI) { \ + SLJIT_ASSERT(!(src & SLJIT_MEM) || (src & 0xf) != SLJIT_LOCALS_REG); \ + SLJIT_ASSERT(!(dst & SLJIT_MEM) || (dst & 0xf) != SLJIT_LOCALS_REG); \ + if ((src & SLJIT_MEM) && (src & 0xf)) \ + SLJIT_ASSERT((dst & 0xf) != (src & 0xf) && ((dst >> 4) & 0xf) != (src & 0xf)); \ + } + +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + +SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose) +{ + compiler->verbose = verbose; +} + +static char* reg_names[] = { + (char*)"", (char*)"t1", (char*)"t2", (char*)"t3", + (char*)"te1", (char*)"te2", (char*)"s1", (char*)"s2", + (char*)"s3", (char*)"se1", (char*)"se2", (char*)"lcr" +}; + +static char* freg_names[] = { + (char*)"", (char*)"float_r1", (char*)"float_r2", (char*)"float_r3", (char*)"float_r4" +}; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#ifdef _WIN64 + #define SLJIT_PRINT_D "I64" +#else + #define SLJIT_PRINT_D "l" +#endif +#else + #define SLJIT_PRINT_D "" +#endif + +#define sljit_verbose_param(p, i) \ + if ((p) & SLJIT_IMM) \ + fprintf(compiler->verbose, "#%"SLJIT_PRINT_D"d", (i)); \ + else if ((p) & SLJIT_MEM) { \ + if ((p) & 0xf) { \ + if (i) { \ + if (((p) >> 4) & 0xf) \ + fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \ + else \ + fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \ + } \ + else { \ + if (((p) >> 4) & 0xf) \ + fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \ + else \ + fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \ + } \ + } \ + else \ + fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \ + } else \ + fprintf(compiler->verbose, "%s", reg_names[p]); +#define sljit_verbose_fparam(p, i) \ + if ((p) & SLJIT_MEM) { \ + if ((p) & 0xf) { \ + if (i) { \ + if (((p) >> 4) & 0xf) \ + fprintf(compiler->verbose, "[%s + %s * %d]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF], 1 << (i)); \ + else \ + fprintf(compiler->verbose, "[%s + #%"SLJIT_PRINT_D"d]", reg_names[(p) & 0xF], (i)); \ + } \ + else { \ + if (((p) >> 4) & 0xF) \ + fprintf(compiler->verbose, "[%s + %s]", reg_names[(p) & 0xF], reg_names[((p) >> 4)& 0xF]); \ + else \ + fprintf(compiler->verbose, "[%s]", reg_names[(p) & 0xF]); \ + } \ + } \ + else \ + fprintf(compiler->verbose, "[#%"SLJIT_PRINT_D"d]", (i)); \ + } else \ + fprintf(compiler->verbose, "%s", freg_names[p]); + +static SLJIT_CONST char* op_names[] = { + /* op0 */ + (char*)"breakpoint", (char*)"nop", + (char*)"umul", (char*)"smul", (char*)"udiv", (char*)"sdiv", + /* op1 */ + (char*)"mov", (char*)"mov.ub", (char*)"mov.sb", (char*)"mov.uh", + (char*)"mov.sh", (char*)"mov.ui", (char*)"mov.si", (char*)"movu", + (char*)"movu.ub", (char*)"movu.sb", (char*)"movu.uh", (char*)"movu.sh", + (char*)"movu.ui", (char*)"movu.si", (char*)"not", (char*)"neg", + (char*)"clz", + /* op2 */ + (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc", + (char*)"mul", (char*)"and", (char*)"or", (char*)"xor", + (char*)"shl", (char*)"lshr", (char*)"ashr", + /* fop1 */ + (char*)"fcmp", (char*)"fmov", (char*)"fneg", (char*)"fabs", + /* fop2 */ + (char*)"fadd", (char*)"fsub", (char*)"fmul", (char*)"fdiv" +}; + +static char* jump_names[] = { + (char*)"c_equal", (char*)"c_not_equal", + (char*)"c_less", (char*)"c_greater_equal", + (char*)"c_greater", (char*)"c_less_equal", + (char*)"c_sig_less", (char*)"c_sig_greater_equal", + (char*)"c_sig_greater", (char*)"c_sig_less_equal", + (char*)"c_overflow", (char*)"c_not_overflow", + (char*)"c_mul_overflow", (char*)"c_mul_not_overflow", + (char*)"c_float_equal", (char*)"c_float_not_equal", + (char*)"c_float_less", (char*)"c_float_greater_equal", + (char*)"c_float_greater", (char*)"c_float_less_equal", + (char*)"c_float_nan", (char*)"c_float_not_nan", + (char*)"jump", (char*)"fast_call", + (char*)"call0", (char*)"call1", (char*)"call2", (char*)"call3" +}; + +#endif + +/* --------------------------------------------------------------------- */ +/* Arch dependent */ +/* --------------------------------------------------------------------- */ + +static SLJIT_INLINE void check_sljit_generate_code(struct sljit_compiler *compiler) +{ +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + struct sljit_jump *jump; +#endif + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + + SLJIT_ASSERT(compiler->size > 0); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + jump = compiler->jumps; + while (jump) { + /* All jumps have target. */ + SLJIT_ASSERT(jump->flags & (JUMP_LABEL | JUMP_ADDR)); + jump = jump->next; + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + + SLJIT_ASSERT(args >= 0 && args <= 3); + SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS); + SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS); + SLJIT_ASSERT(args <= saveds); + SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + fprintf(compiler->verbose, " enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size); +#endif +} + +static SLJIT_INLINE void check_sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + + SLJIT_ASSERT(args >= 0 && args <= 3); + SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS); + SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS); + SLJIT_ASSERT(args <= saveds); + SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + fprintf(compiler->verbose, " fake_enter args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size); +#endif +} + +static SLJIT_INLINE void check_sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (op != SLJIT_UNUSED) { + SLJIT_ASSERT(op >= SLJIT_MOV && op <= SLJIT_MOV_SI); + FUNCTION_CHECK_SRC(src, srcw); + } + else + SLJIT_ASSERT(src == 0 && srcw == 0); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + if (op == SLJIT_UNUSED) + fprintf(compiler->verbose, " return\n"); + else { + fprintf(compiler->verbose, " return %s ", op_names[op]); + sljit_verbose_param(src, srcw); + fprintf(compiler->verbose, "\n"); + } + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + + SLJIT_ASSERT(args >= 0 && args <= 3); + SLJIT_ASSERT(temporaries >= 0 && temporaries <= SLJIT_NO_TMP_REGISTERS); + SLJIT_ASSERT(saveds >= 0 && saveds <= SLJIT_NO_GEN_REGISTERS); + SLJIT_ASSERT(args <= saveds); + SLJIT_ASSERT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->temporaries = temporaries; + compiler->saveds = saveds; + FUNCTION_CHECK_DST(dst, dstw); + compiler->temporaries = -1; + compiler->saveds = -1; +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fast_enter "); + sljit_verbose_param(dst, dstw); + fprintf(compiler->verbose, " args=%d temporaries=%d saveds=%d local_size=%d\n", args, temporaries, saveds, local_size); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_SRC(src, srcw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fast_return "); + sljit_verbose_param(src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + + SLJIT_ASSERT((op >= SLJIT_BREAKPOINT && op <= SLJIT_SMUL) + || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIV && (op & ~SLJIT_INT_OP) <= SLJIT_SDIV)); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + fprintf(compiler->verbose, " %s%s\n", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)]); +#endif +} + +static SLJIT_INLINE void check_sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + return; + } +#endif + + SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_CLZ); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_OP(); + FUNCTION_CHECK_SRC(src, srcw); + FUNCTION_CHECK_DST(dst, dstw); + FUNCTION_CHECK_OP1(); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)], + !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K"); + sljit_verbose_param(dst, dstw); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + return; + } +#endif + + SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_ADD && GET_OPCODE(op) <= SLJIT_ASHR); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_OP(); + FUNCTION_CHECK_SRC(src1, src1w); + FUNCTION_CHECK_SRC(src2, src2w); + FUNCTION_CHECK_DST(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s%s%s%s%s%s%s ", !(op & SLJIT_INT_OP) ? "" : "i", op_names[GET_OPCODE(op)], + !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S", !(op & SLJIT_SET_U) ? "" : "U", !(op & SLJIT_SET_O) ? "" : "O", !(op & SLJIT_SET_C) ? "" : "C", !(op & SLJIT_KEEP_FLAGS) ? "" : "K"); + sljit_verbose_param(dst, dstw); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_get_register_index(int reg) +{ + SLJIT_UNUSED_ARG(reg); + SLJIT_ASSERT(reg > 0 && reg <= SLJIT_NO_REGISTERS); +} + +static SLJIT_INLINE void check_sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(instruction); + SLJIT_UNUSED_ARG(size); + SLJIT_ASSERT(instruction); +} + +static SLJIT_INLINE void check_sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + return; + } +#endif + + SLJIT_ASSERT(sljit_is_fpu_available()); + SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FCMP && GET_OPCODE(op) <= SLJIT_FABS); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_OP(); + FUNCTION_FCHECK(src, srcw); + FUNCTION_FCHECK(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s%s%s ", op_names[GET_OPCODE(op)], + !(op & SLJIT_SET_E) ? "" : "E", !(op & SLJIT_SET_S) ? "" : "S"); + sljit_verbose_fparam(dst, dstw); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + + SLJIT_ASSERT(sljit_is_fpu_available()); + SLJIT_ASSERT(GET_OPCODE(op) >= SLJIT_FADD && GET_OPCODE(op) <= SLJIT_FDIV); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_OP(); + FUNCTION_FCHECK(src1, src1w); + FUNCTION_FCHECK(src2, src2w); + FUNCTION_FCHECK(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s ", op_names[GET_OPCODE(op)]); + sljit_verbose_fparam(dst, dstw); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_label(struct sljit_compiler *compiler) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + fprintf(compiler->verbose, "label:\n"); +#endif +} + +static SLJIT_INLINE void check_sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + if (SLJIT_UNLIKELY(compiler->skip_checks)) { + compiler->skip_checks = 0; + return; + } +#endif + + SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); + SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_CALL3); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) + fprintf(compiler->verbose, " jump%s <%s>\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]); +#endif +} + +static SLJIT_INLINE void check_sljit_emit_cmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + + SLJIT_ASSERT(!(type & ~(0xff | SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP))); + SLJIT_ASSERT((type & 0xff) >= SLJIT_C_EQUAL && (type & 0xff) <= SLJIT_C_SIG_LESS_EQUAL); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_SRC(src1, src1w); + FUNCTION_CHECK_SRC(src2, src2w); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %scmp%s <%s> ", !(type & SLJIT_INT_OP) ? "" : "i", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]); + sljit_verbose_param(src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + + SLJIT_ASSERT(sljit_is_fpu_available()); + SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP))); + SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_FCHECK(src1, src1w); + FUNCTION_FCHECK(src2, src2w); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]); + sljit_verbose_fparam(src1, src1w); + fprintf(compiler->verbose, ", "); + sljit_verbose_fparam(src2, src2w); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_SRC(src, srcw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " ijump <%s> ", jump_names[type]); + sljit_verbose_param(src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(type); + + SLJIT_ASSERT(type >= SLJIT_C_EQUAL && type < SLJIT_JUMP); + SLJIT_ASSERT(op == SLJIT_MOV || GET_OPCODE(op) == SLJIT_OR); + SLJIT_ASSERT(GET_ALL_FLAGS(op) == 0 || GET_ALL_FLAGS(op) == SLJIT_SET_E || GET_ALL_FLAGS(op) == SLJIT_KEEP_FLAGS); +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_DST(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " cond_set%s%s <%s> ", !(op & SLJIT_SET_E) ? "" : "E", + !(op & SLJIT_KEEP_FLAGS) ? "" : "K", op_names[GET_OPCODE(op)]); + sljit_verbose_param(dst, dstw); + fprintf(compiler->verbose, ", <%s>\n", jump_names[type]); + } +#endif +} + +static SLJIT_INLINE void check_sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + /* If debug and verbose are disabled, all arguments are unused. */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(init_value); + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG) + FUNCTION_CHECK_DST(dst, dstw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " const "); + sljit_verbose_param(dst, dstw); + fprintf(compiler->verbose, ", #%"SLJIT_PRINT_D"d\n", init_value); + } +#endif +} + +static SLJIT_INLINE int emit_mov_before_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + /* Return if don't need to do anything. */ + if (op == SLJIT_UNUSED) + return SLJIT_SUCCESS; + +#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) + if (src == SLJIT_RETURN_REG && op == SLJIT_MOV) + return SLJIT_SUCCESS; +#else + if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI)) + return SLJIT_SUCCESS; +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw); +} + +/* CPU description section */ + +#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE) +#define SLJIT_CPUINFO_PART1 " 32bit (" +#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#define SLJIT_CPUINFO_PART1 " 64bit (" +#else +#error "Internal error: CPU type info missing" +#endif + +#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN) +#define SLJIT_CPUINFO_PART2 "little endian + " +#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) +#define SLJIT_CPUINFO_PART2 "big endian + " +#else +#error "Internal error: CPU type info missing" +#endif + +#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) +#define SLJIT_CPUINFO_PART3 "unaligned)" +#else +#define SLJIT_CPUINFO_PART3 "aligned)" +#endif + +#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3 + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + #include "sljitNativeX86_common.c" +#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + #include "sljitNativeX86_common.c" +#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + #include "sljitNativeARM_v5.c" +#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + #include "sljitNativeARM_v5.c" +#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) + #include "sljitNativeARM_Thumb2.c" +#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + #include "sljitNativePPC_common.c" +#elif (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + #include "sljitNativePPC_common.c" +#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #include "sljitNativeMIPS_common.c" +#endif + +#if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* Default compare for most architectures. */ + int flags, tmp_src, condition; + sljit_w tmp_srcw; + + CHECK_ERROR_PTR(); + check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w); + + condition = type & 0xff; + if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) { + /* Immediate is prefered as second argument by most architectures. */ + switch (condition) { + case SLJIT_C_LESS: + condition = SLJIT_C_GREATER; + break; + case SLJIT_C_GREATER_EQUAL: + condition = SLJIT_C_LESS_EQUAL; + break; + case SLJIT_C_GREATER: + condition = SLJIT_C_LESS; + break; + case SLJIT_C_LESS_EQUAL: + condition = SLJIT_C_GREATER_EQUAL; + break; + case SLJIT_C_SIG_LESS: + condition = SLJIT_C_SIG_GREATER; + break; + case SLJIT_C_SIG_GREATER_EQUAL: + condition = SLJIT_C_SIG_LESS_EQUAL; + break; + case SLJIT_C_SIG_GREATER: + condition = SLJIT_C_SIG_LESS; + break; + case SLJIT_C_SIG_LESS_EQUAL: + condition = SLJIT_C_SIG_GREATER_EQUAL; + break; + } + type = condition | (type & (SLJIT_INT_OP | SLJIT_REWRITABLE_JUMP)); + tmp_src = src1; + src1 = src2; + src2 = tmp_src; + tmp_srcw = src1w; + src1w = src2w; + src2w = tmp_srcw; + } + + if (condition <= SLJIT_C_NOT_ZERO) + flags = SLJIT_SET_E; + else if (condition <= SLJIT_C_LESS_EQUAL) + flags = SLJIT_SET_U; + else + flags = SLJIT_SET_S; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_INT_OP), + SLJIT_UNUSED, 0, src1, src1w, src2, src2w)); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int flags, condition; + + check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w); + + condition = type & 0xff; + if (condition <= SLJIT_C_FLOAT_NOT_EQUAL) + flags = SLJIT_SET_E; + else + flags = SLJIT_SET_S; + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP)); +} + +#endif + +#else /* SLJIT_CONFIG_UNSUPPORTED */ + +/* Empty function bodies for those machines, which are not (yet) supported. */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ + return "unsupported"; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void) +{ + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(size); + SLJIT_ASSERT_STOP(); + return NULL; +} + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(verbose); + SLJIT_ASSERT_STOP(); +} +#endif + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +{ + SLJIT_UNUSED_ARG(code); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(args); + SLJIT_UNUSED_ARG(temporaries); + SLJIT_UNUSED_ARG(saveds); + SLJIT_UNUSED_ARG(local_size); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + SLJIT_ASSERT_STOP(); + return reg; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(instruction); + SLJIT_UNUSED_ARG(size); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + SLJIT_ASSERT_STOP(); + return 0; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src1); + SLJIT_UNUSED_ARG(src1w); + SLJIT_UNUSED_ARG(src2); + SLJIT_UNUSED_ARG(src2w); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label) +{ + SLJIT_UNUSED_ARG(jump); + SLJIT_UNUSED_ARG(label); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target) +{ + SLJIT_UNUSED_ARG(jump); + SLJIT_UNUSED_ARG(target); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(type); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(type); + SLJIT_ASSERT_STOP(); + return SLJIT_ERR_UNSUPPORTED; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w initval) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(dst); + SLJIT_UNUSED_ARG(dstw); + SLJIT_UNUSED_ARG(initval); + SLJIT_ASSERT_STOP(); + return NULL; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + SLJIT_UNUSED_ARG(addr); + SLJIT_UNUSED_ARG(new_addr); + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + SLJIT_UNUSED_ARG(addr); + SLJIT_UNUSED_ARG(new_constant); + SLJIT_ASSERT_STOP(); +} + +#endif diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h new file mode 100644 index 0000000000..0cb1c1e589 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitLir.h @@ -0,0 +1,853 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SLJIT_LIR_H_ +#define _SLJIT_LIR_H_ + +/* + ------------------------------------------------------------------------ + Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC) + ------------------------------------------------------------------------ + + Short description + Advantages: + - The execution can be continued from any LIR instruction + In other words, jump into and out of the code is safe + - Both target of (conditional) jump and call instructions + and constants can be dynamically modified during runtime + - although it is not suggested to do it frequently + - very effective to cache an important value once + - A fixed stack space can be allocated for local variables + - The compiler is thread-safe + Disadvantages: + - Limited number of registers (only 6+4 integer registers, max 3+2 + temporary, max 3+2 saved and 4 floating point registers) + In practice: + - This approach is very effective for interpreters + - One of the saved registers typically points to a stack interface + - It can jump to any exception handler anytime (even for another + function. It is safe for SLJIT.) + - Fast paths can be modified during runtime reflecting the changes + of the fastest execution path of the dynamic language + - SLJIT supports complex memory addressing modes + - mainly position independent code + - Optimizations (perhaps later) + - Only for basic blocks (when no labels inserted between LIR instructions) + + For valgrind users: + - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code" +*/ + +#if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG) +#include "sljitConfig.h" +#endif + +/* The following header file defines useful macros for fine tuning +sljit based code generators. They are listed in the begining +of sljitConfigInternal.h */ + +#include "sljitConfigInternal.h" + +/* --------------------------------------------------------------------- */ +/* Error codes */ +/* --------------------------------------------------------------------- */ + +/* Indicates no error. */ +#define SLJIT_SUCCESS 0 +/* After the call of sljit_generate_code(), the error code of the compiler + is set to this value to avoid future sljit calls (in debug mode at least). + The complier should be freed after sljit_generate_code(). */ +#define SLJIT_ERR_COMPILED 1 +/* Cannot allocate non executable memory. */ +#define SLJIT_ERR_ALLOC_FAILED 2 +/* Cannot allocate executable memory. + Only for sljit_generate_code() */ +#define SLJIT_ERR_EX_ALLOC_FAILED 3 +/* return value for SLJIT_CONFIG_UNSUPPORTED empty architecture. */ +#define SLJIT_ERR_UNSUPPORTED 4 + +/* --------------------------------------------------------------------- */ +/* Registers */ +/* --------------------------------------------------------------------- */ + +#define SLJIT_UNUSED 0 + +/* Temporary (scratch) registers may not preserve their values across function calls. */ +#define SLJIT_TEMPORARY_REG1 1 +#define SLJIT_TEMPORARY_REG2 2 +#define SLJIT_TEMPORARY_REG3 3 +/* Note: Extra Registers cannot be used for memory addressing. */ +/* Note: on x86-32, these registers are emulated (using stack loads & stores). */ +#define SLJIT_TEMPORARY_EREG1 4 +#define SLJIT_TEMPORARY_EREG2 5 + +/* Saved registers whose preserve their values across function calls. */ +#define SLJIT_SAVED_REG1 6 +#define SLJIT_SAVED_REG2 7 +#define SLJIT_SAVED_REG3 8 +/* Note: Extra Registers cannot be used for memory addressing. */ +/* Note: on x86-32, these registers are emulated (using stack loads & stores). */ +#define SLJIT_SAVED_EREG1 9 +#define SLJIT_SAVED_EREG2 10 + +/* Read-only register (cannot be the destination of an operation). */ +/* Note: SLJIT_MEM2( ... , SLJIT_LOCALS_REG) is not supported (x86 limitation). */ +/* Note: SLJIT_LOCALS_REG is not necessary the real stack pointer. See sljit_emit_enter. */ +#define SLJIT_LOCALS_REG 11 + +/* Number of registers. */ +#define SLJIT_NO_TMP_REGISTERS 5 +#define SLJIT_NO_GEN_REGISTERS 5 +#define SLJIT_NO_REGISTERS 11 + +/* Return with machine word. */ + +#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1 + +/* x86 prefers specific registers for special purposes. In case of shift + by register it supports only SLJIT_TEMPORARY_REG3 for shift argument + (which is the src2 argument of sljit_emit_op2). If another register is + used, sljit must exchange data between registers which cause a minor + slowdown. Other architectures has no such limitation. */ + +#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3 + +/* --------------------------------------------------------------------- */ +/* Floating point registers */ +/* --------------------------------------------------------------------- */ + +/* Note: SLJIT_UNUSED as destination is not valid for floating point + operations, since they cannot be used for setting flags. */ + +/* Floating point operations are performed on double precision values. */ + +#define SLJIT_FLOAT_REG1 1 +#define SLJIT_FLOAT_REG2 2 +#define SLJIT_FLOAT_REG3 3 +#define SLJIT_FLOAT_REG4 4 + +/* --------------------------------------------------------------------- */ +/* Main structures and functions */ +/* --------------------------------------------------------------------- */ + +struct sljit_memory_fragment { + struct sljit_memory_fragment *next; + sljit_uw used_size; + sljit_ub memory[1]; +}; + +struct sljit_label { + struct sljit_label *next; + sljit_uw addr; + /* The maximum size difference. */ + sljit_uw size; +}; + +struct sljit_jump { + struct sljit_jump *next; + sljit_uw addr; + sljit_w flags; + union { + sljit_uw target; + struct sljit_label* label; + } u; +}; + +struct sljit_const { + struct sljit_const *next; + sljit_uw addr; +}; + +struct sljit_compiler { + int error; + + struct sljit_label *labels; + struct sljit_jump *jumps; + struct sljit_const *consts; + struct sljit_label *last_label; + struct sljit_jump *last_jump; + struct sljit_const *last_const; + + struct sljit_memory_fragment *buf; + struct sljit_memory_fragment *abuf; + + /* Used local registers. */ + int temporaries; + /* Used saved registers. */ + int saveds; + /* Local stack size. */ + int local_size; + /* Code size. */ + sljit_uw size; + /* For statistical purposes. */ + sljit_uw executable_size; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + int args; + int temporaries_start; + int saveds_start; +#endif + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + int mode32; +#ifdef _WIN64 + int has_locals; +#endif +#endif + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + int flags_saved; +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + /* Constant pool handling. */ + sljit_uw *cpool; + sljit_ub *cpool_unique; + sljit_uw cpool_diff; + sljit_uw cpool_fill; + /* Other members. */ + /* Contains pointer, "ldr pc, [...]" pairs. */ + sljit_uw patches; +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + /* Temporary fields. */ + sljit_uw shift_imm; + int cache_arg; + sljit_w cache_argw; +#endif + +#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) + int cache_arg; + sljit_w cache_argw; +#endif + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + int has_locals; + sljit_w imm; + int cache_arg; + sljit_w cache_argw; +#endif + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + int has_locals; + int delay_slot; + int cache_arg; + sljit_w cache_argw; +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + FILE* verbose; +#endif + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + int skip_checks; +#endif +}; + +/* --------------------------------------------------------------------- */ +/* Main functions */ +/* --------------------------------------------------------------------- */ + +/* Creates an sljit compiler. + Returns NULL if failed. */ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void); +/* Free everything except the codes. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); + +static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; } + +/* + Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit, + and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler, + and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned. + Excellent for allocating small blocks during the compiling, and no need to worry + about freeing them. The size is enough to contain at most 16 pointers. + If the size is outside of the range, the function will return with NULL, + but this return value does not indicate that there is no more memory (does + not set the compiler to out-of-memory status). +*/ +SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) +/* Passing NULL disables verbose. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose); +#endif + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler); +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); + +/* + After the code generation we can retrieve the allocated executable memory size, + although this area may not be fully filled with instructions depending on some + optimizations. This function is useful only for statistical purposes. + + Before a successful code generation, this function returns with 0. +*/ +static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; } + +/* Instruction generation. Returns with error code. */ + +/* + The executable code is basically a function call from the viewpoint of + the C language. The function calls must obey to the ABI (Application + Binary Interface) of the platform, which specify the purpose of machine + registers and stack handling among other things. The sljit_emit_enter + function emits the necessary instructions for setting up a new context + for the executable code and moves function arguments to the saved + registers. The number of arguments are specified in the "args" + parameter and the first argument goes to SLJIT_SAVED_REG1, the second + goes to SLJIT_SAVED_REG2 and so on. The number of temporary and + saved registers are passed in "temporaries" and "saveds" arguments + respectively. Since the saved registers contains the arguments, + "args" must be less or equal than "saveds". The sljit_emit_enter + is also capable of allocating a stack space for local variables. The + "local_size" argument contains the size in bytes of this local area + and its staring address is stored in SLJIT_LOCALS_REG. However + the SLJIT_LOCALS_REG is not necessary the machine stack pointer. + The memory bytes between SLJIT_LOCALS_REG (inclusive) and + SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely + until the function returns. The stack space is uninitialized. + + Note: every call of sljit_emit_enter and sljit_set_context overwrites + the previous context. */ + +#define SLJIT_MAX_LOCAL_SIZE 65536 + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, + int args, int temporaries, int saveds, int local_size); + +/* The machine code has a context (which contains the local stack space size, + number of used registers, etc.) which initialized by sljit_emit_enter. Several + functions (like sljit_emit_return) requres this context to be able to generate + the appropriate code. However, some code fragments (like inline cache) may have + no normal entry point so their context is unknown for the compiler. Using the + function below we can specify thir context. + + Note: every call of sljit_emit_enter and sljit_set_context overwrites + the previous context. */ + +/* Note: multiple calls of this function overwrites the previous call. */ + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, + int args, int temporaries, int saveds, int local_size); + +/* Return from machine code. The op argument can be SLJIT_UNUSED which means the + function does not return with anything or any opcode between SLJIT_MOV and + SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op + is SLJIT_UNUSED, otherwise see below the description about source and + destination arguments. */ +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, + int src, sljit_w srcw); + +/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL). + All registers and even the stack frame is passed to the callee. The return address is + preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can + use this as a return value later. */ + +/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions + are needed. Excellent for small uility functions, where saving registers and setting up + a new stack frame would cost too much performance. However, it is still possible to return + to the address of the caller (or anywhere else). */ + +/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */ + +/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested, + since many architectures do clever branch prediction on call / return instruction pairs. */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size); +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw); + +/* + Source and destination values for arithmetical instructions + imm - a simple immediate value (cannot be used as a destination) + reg - any of the registers (immediate argument must be 0) + [imm] - absolute immediate memory address + [reg+imm] - indirect memory address + [reg+(reg<addr; } +static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; } +static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; } + +/* Only the address is required to rewrite the code. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr); +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant); + +/* --------------------------------------------------------------------- */ +/* Miscellaneous utility functions */ +/* --------------------------------------------------------------------- */ + +#define SLJIT_MAJOR_VERSION 0 +#define SLJIT_MINOR_VERSION 87 + +/* Get the human readable name of the platfrom. + Can be useful for debugging on platforms like ARM, where ARM and + Thumb2 functions can be mixed. */ +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void); + +/* Portble helper function to get an offset of a member. */ +#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10) + +#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) +/* This global lock is useful to compile common functions. */ +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void); +#endif + +#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) + +/* The sljit_stack is a utiliy feature of sljit, which allocates a + writable memory region between base (inclusive) and limit (exclusive). + Both base and limit is a pointer, and base is always <= than limit. + This feature uses the "address space reserve" feature + of modern operating systems. Basically we don't need to allocate a + huge memory block in one step for the worst case, we can start with + a smaller chunk and extend it later. Since the address space is + reserved, the data never copied to other regions, thus it is safe + to store pointers here. */ + +/* Note: The base field is aligned to PAGE_SIZE bytes (usually 4k or more). + Note: stack growing should not happen in small steps: 4k, 16k or even + bigger growth is better. + Note: this structure may not be supported by all operating systems. + Some kind of fallback mechanism is suggested when SLJIT_UTIL_STACK + is not defined. */ + +struct sljit_stack { + /* User data, anything can be stored here. + Starting with the same value as base. */ + sljit_uw top; + /* These members are read only. */ + sljit_uw base; + sljit_uw limit; + sljit_uw max_limit; +}; + +/* Returns NULL if unsuccessful. + Note: limit and max_limit contains the size for stack allocation + Note: the top field is initialized to base. */ +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit); +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack); + +/* Can be used to increase (allocate) or decrease (free) the memory area. + Returns with a non-zero value if unsuccessful. If new_limit is greater than + max_limit, it will fail. It is very easy to implement a stack data structure, + since the growth ratio can be added to the current limit, and sljit_stack_resize + will do all the necessary checks. The fields of the stack are not changed if + sljit_stack_resize fails. */ +SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit); + +#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */ + +#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) + +/* Get the entry address of a given function. */ +#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)func_name) + +#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ + +/* All JIT related code should be placed in the same context (library, binary, etc.). */ + +#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)*(void**)func_name) + +/* For powerpc64, the function pointers point to a context descriptor. */ +struct sljit_function_context { + sljit_w addr; + sljit_w r2; + sljit_w r11; +}; + +/* Fill the context arguments using the addr and the function. + If func_ptr is NULL, it will not be set to the address of context + If addr is NULL, the function address also comes from the func pointer. */ +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func); + +#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ + +#endif /* _SLJIT_LIR_H_ */ diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c b/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c new file mode 100644 index 0000000000..a51536b4a7 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_Thumb2.c @@ -0,0 +1,1913 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ + return "ARM-Thumb2" SLJIT_CPUINFO; +} + +/* Last register + 1. */ +#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) +#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) +#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) +#define TMP_PC (SLJIT_NO_REGISTERS + 4) + +#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) +#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2) + +/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { + 0, 0, 1, 2, 12, 5, 6, 7, 8, 10, 11, 13, 3, 4, 14, 15 +}; + +#define COPY_BITS(src, from, to, bits) \ + ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to)) + +/* Thumb16 encodings. */ +#define RD3(rd) (reg_map[rd]) +#define RN3(rn) (reg_map[rn] << 3) +#define RM3(rm) (reg_map[rm] << 6) +#define RDN3(rdn) (reg_map[rdn] << 8) +#define IMM3(imm) (imm << 6) +#define IMM8(imm) (imm) + +/* Thumb16 helpers. */ +#define SET_REGS44(rd, rn) \ + ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4)) +#define IS_2_LO_REGS(reg1, reg2) \ + (reg_map[reg1] <= 7 && reg_map[reg2] <= 7) +#define IS_3_LO_REGS(reg1, reg2, reg3) \ + (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7) + +/* Thumb32 encodings. */ +#define RD4(rd) (reg_map[rd] << 8) +#define RN4(rn) (reg_map[rn] << 16) +#define RM4(rm) (reg_map[rm]) +#define RT4(rt) (reg_map[rt] << 12) +#define DD4(dd) ((dd) << 12) +#define DN4(dn) ((dn) << 16) +#define DM4(dm) (dm) +#define IMM5(imm) \ + (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6)) +#define IMM12(imm) \ + (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)) + +typedef sljit_ui sljit_ins; + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ + +/* dot '.' changed to _ + I immediate form (possibly followed by number of immediate bits). */ +#define ADCI 0xf1400000 +#define ADCS 0x4140 +#define ADC_W 0xeb400000 +#define ADD 0x4400 +#define ADDS 0x1800 +#define ADDSI3 0x1c00 +#define ADDSI8 0x3000 +#define ADD_W 0xeb000000 +#define ADDWI 0xf2000000 +#define ADD_SP 0xb000 +#define ADD_W 0xeb000000 +#define ADD_WI 0xf1000000 +#define ANDI 0xf0000000 +#define ANDS 0x4000 +#define AND_W 0xea000000 +#define ASRS 0x4100 +#define ASRSI 0x1000 +#define ASR_W 0xfa40f000 +#define ASR_WI 0xea4f0020 +#define BICI 0xf0200000 +#define BKPT 0xbe00 +#define BLX 0x4780 +#define BX 0x4700 +#define CLZ 0xfab0f080 +#define CMPI 0x2800 +#define CMP_W 0xebb00f00 +#define EORI 0xf0800000 +#define EORS 0x4040 +#define EOR_W 0xea800000 +#define IT 0xbf00 +#define LSLS 0x4080 +#define LSLSI 0x0000 +#define LSL_W 0xfa00f000 +#define LSL_WI 0xea4f0000 +#define LSRS 0x40c0 +#define LSRSI 0x0800 +#define LSR_W 0xfa20f000 +#define LSR_WI 0xea4f0010 +#define MOV 0x4600 +#define MOVS 0x0000 +#define MOVSI 0x2000 +#define MOVT 0xf2c00000 +#define MOVW 0xf2400000 +#define MOV_W 0xea4f0000 +#define MOV_WI 0xf04f0000 +#define MUL 0xfb00f000 +#define MVNS 0x43c0 +#define MVN_W 0xea6f0000 +#define MVN_WI 0xf06f0000 +#define NOP 0xbf00 +#define ORNI 0xf0600000 +#define ORRI 0xf0400000 +#define ORRS 0x4300 +#define ORR_W 0xea400000 +#define POP 0xbd00 +#define POP_W 0xe8bd0000 +#define PUSH 0xb500 +#define PUSH_W 0xe92d0000 +#define RSB_WI 0xf1c00000 +#define RSBSI 0x4240 +#define SBCI 0xf1600000 +#define SBCS 0x4180 +#define SBC_W 0xeb600000 +#define SMULL 0xfb800000 +#define STR_SP 0x9000 +#define SUBS 0x1a00 +#define SUBSI3 0x1e00 +#define SUBSI8 0x3800 +#define SUB_W 0xeba00000 +#define SUBWI 0xf2a00000 +#define SUB_SP 0xb080 +#define SUB_WI 0xf1a00000 +#define SXTB 0xb240 +#define SXTB_W 0xfa4ff080 +#define SXTH 0xb200 +#define SXTH_W 0xfa0ff080 +#define TST 0x4200 +#define UMULL 0xfba00000 +#define UXTB 0xb2c0 +#define UXTB_W 0xfa5ff080 +#define UXTH 0xb280 +#define UXTH_W 0xfa1ff080 +#define VABS_F64 0xeeb00bc0 +#define VADD_F64 0xee300b00 +#define VCMP_F64 0xeeb40b40 +#define VDIV_F64 0xee800b00 +#define VMOV_F64 0xeeb00b40 +#define VMRS 0xeef1fa10 +#define VMUL_F64 0xee200b00 +#define VNEG_F64 0xeeb10b40 +#define VSTR 0xed000b00 +#define VSUB_F64 0xee300b40 + +static int push_inst16(struct sljit_compiler *compiler, sljit_ins inst) +{ + sljit_uh *ptr; + SLJIT_ASSERT(!(inst & 0xffff0000)); + + ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_uh)); + FAIL_IF(!ptr); + *ptr = inst; + compiler->size++; + return SLJIT_SUCCESS; +} + +static int push_inst32(struct sljit_compiler *compiler, sljit_ins inst) +{ + sljit_uh *ptr = (sljit_uh*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + *ptr++ = inst >> 16; + *ptr = inst; + compiler->size += 2; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_imm32_const(struct sljit_compiler *compiler, int dst, sljit_uw imm) +{ + FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | + COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); + return push_inst32(compiler, MOVT | RD4(dst) | + COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); +} + +static SLJIT_INLINE void modify_imm32_const(sljit_uh* inst, sljit_uw new_imm) +{ + int dst = inst[1] & 0x0f00; + SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00)); + inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1); + inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff); + inst[2] = (MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1); + inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16); +} + +static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uh *code_ptr, sljit_uh *code) +{ + sljit_w diff; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + return 0; + + if (jump->flags & JUMP_ADDR) { + /* Branch to ARM code is not optimized yet. */ + if (!(jump->u.target & 0x1)) + return 0; + diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)) >> 1; + } + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2)) >> 1; + } + + if (jump->flags & IS_CONDITIONAL) { + SLJIT_ASSERT(!(jump->flags & IS_BL)); + if (diff <= 127 && diff >= -128) { + jump->flags |= B_TYPE1; + return 5; + } + if (diff <= 524287 && diff >= -524288) { + jump->flags |= B_TYPE2; + return 4; + } + /* +1 comes from the prefix IT instruction. */ + diff--; + if (diff <= 8388607 && diff >= -8388608) { + jump->flags |= B_TYPE3; + return 3; + } + } + else if (jump->flags & IS_BL) { + if (diff <= 8388607 && diff >= -8388608) { + jump->flags |= BL_TYPE6; + return 3; + } + } + else { + if (diff <= 1023 && diff >= -1024) { + jump->flags |= B_TYPE4; + return 4; + } + if (diff <= 8388607 && diff >= -8388608) { + jump->flags |= B_TYPE5; + return 3; + } + } + + return 0; +} + +static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush) +{ + sljit_uh* inst = (sljit_uh*)addr; + modify_imm32_const(inst, new_addr); + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 3); + } +} + +static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump) +{ + int type = (jump->flags >> 4) & 0xf; + sljit_w diff; + sljit_uh *jump_inst; + int s, j1, j2; + + if (SLJIT_UNLIKELY(type == 0)) { + inline_set_jump_addr(jump->addr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); + return; + } + + if (jump->flags & JUMP_ADDR) { + SLJIT_ASSERT(jump->u.target & 0x1); + diff = ((sljit_w)jump->u.target - (sljit_w)(jump->addr + 4)) >> 1; + } + else + diff = ((sljit_w)(jump->u.label->addr) - (sljit_w)(jump->addr + 4)) >> 1; + jump_inst = (sljit_uh*)jump->addr; + + switch (type) { + case 1: + /* Encoding T1 of 'B' instruction */ + SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_CONDITIONAL)); + jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff); + return; + case 2: + /* Encoding T3 of 'B' instruction */ + SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_CONDITIONAL)); + jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1); + jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff); + return; + case 3: + SLJIT_ASSERT(jump->flags & IS_CONDITIONAL); + *jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8; + diff--; + type = 5; + break; + case 4: + /* Encoding T2 of 'B' instruction */ + SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_CONDITIONAL)); + jump_inst[0] = 0xe000 | (diff & 0x7ff); + return; + } + + SLJIT_ASSERT(diff <= 8388607 && diff >= -8388608); + + /* Really complex instruction form for branches. */ + s = (diff >> 23) & 0x1; + j1 = (~(diff >> 21) ^ s) & 0x1; + j2 = (~(diff >> 22) ^ s) & 0x1; + jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10); + jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff); + + /* The others have a common form. */ + if (type == 5) /* Encoding T4 of 'B' instruction */ + jump_inst[1] |= 0x9000; + else if (type == 6) /* Encoding T1 of 'BL' instruction */ + jump_inst[1] |= 0xd000; + else + SLJIT_ASSERT_STOP(); +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_uh *code; + sljit_uh *code_ptr; + sljit_uh *buf_ptr; + sljit_uh *buf_end; + sljit_uw half_count; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + + CHECK_ERROR_PTR(); + check_sljit_generate_code(compiler); + reverse_buf(compiler); + + code = (sljit_uh*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_uh)); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + half_count = 0; + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + + do { + buf_ptr = (sljit_uh*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 1); + do { + *code_ptr = *buf_ptr++; + /* These structures are ordered by their address. */ + SLJIT_ASSERT(!label || label->size >= half_count); + SLJIT_ASSERT(!jump || jump->addr >= half_count); + SLJIT_ASSERT(!const_ || const_->addr >= half_count); + if (label && label->size == half_count) { + label->addr = ((sljit_uw)code_ptr) | 0x1; + label->size = code_ptr - code; + label = label->next; + } + if (jump && jump->addr == half_count) { + jump->addr = (sljit_uw)code_ptr - ((jump->flags & IS_CONDITIONAL) ? 10 : 8); + code_ptr -= detect_jump_type(jump, code_ptr, code); + jump = jump->next; + } + if (const_ && const_->addr == half_count) { + const_->addr = (sljit_uw)code_ptr; + const_ = const_->next; + } + code_ptr ++; + half_count ++; + } while (buf_ptr < buf_end); + + buf = buf->next; + } while (buf); + + if (label && label->size == half_count) { + label->addr = ((sljit_uw)code_ptr) | 0x1; + label->size = code_ptr - code; + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + SLJIT_ASSERT(code_ptr - code <= (int)compiler->size); + + jump = compiler->jumps; + while (jump) { + set_jump_instruction(jump); + jump = jump->next; + } + + SLJIT_CACHE_FLUSH(code, code_ptr); + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_size = compiler->size * sizeof(sljit_uh); + /* Set thumb mode flag. */ + return (void*)((sljit_uw)code | 0x1); +} + +#define INVALID_IMM 0x80000000 +static sljit_uw get_imm(sljit_uw imm) +{ + /* Thumb immediate form. */ + int counter; + + if (imm <= 0xff) + return imm; + + if ((imm & 0xffff) == (imm >> 16)) { + /* Some special cases. */ + if (!(imm & 0xff00)) + return (1 << 12) | (imm & 0xff); + if (!(imm & 0xff)) + return (2 << 12) | ((imm >> 8) & 0xff); + if ((imm & 0xff00) == ((imm & 0xff) << 8)) + return (3 << 12) | (imm & 0xff); + } + + /* Assembly optimization: count leading zeroes? */ + counter = 8; + if (!(imm & 0xffff0000)) { + counter += 16; + imm <<= 16; + } + if (!(imm & 0xff000000)) { + counter += 8; + imm <<= 8; + } + if (!(imm & 0xf0000000)) { + counter += 4; + imm <<= 4; + } + if (!(imm & 0xc0000000)) { + counter += 2; + imm <<= 2; + } + if (!(imm & 0x80000000)) { + counter += 1; + imm <<= 1; + } + /* Since imm >= 128, this must be true. */ + SLJIT_ASSERT(counter <= 31); + + if (imm & 0x00ffffff) + return INVALID_IMM; /* Cannot be encoded. */ + + return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1); +} + +static int load_immediate(struct sljit_compiler *compiler, int dst, sljit_uw imm) +{ + sljit_uw tmp; + + if (imm >= 0x10000) { + tmp = get_imm(imm); + if (tmp != INVALID_IMM) + return push_inst32(compiler, MOV_WI | RD4(dst) | tmp); + tmp = get_imm(~imm); + if (tmp != INVALID_IMM) + return push_inst32(compiler, MVN_WI | RD4(dst) | tmp); + } + + /* set low 16 bits, set hi 16 bits to 0. */ + FAIL_IF(push_inst32(compiler, MOVW | RD4(dst) | + COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))); + + /* set hi 16 bit if needed. */ + if (imm >= 0x10000) + return push_inst32(compiler, MOVT | RD4(dst) | + COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16)); + return SLJIT_SUCCESS; +} + +#define ARG1_IMM 0x0010000 +#define ARG2_IMM 0x0020000 +#define KEEP_FLAGS 0x0040000 +#define SET_MULOV 0x0080000 +/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */ +#define SET_FLAGS 0x0100000 +#define UNUSED_RETURN 0x0200000 +#define SLOW_DEST 0x0400000 +#define SLOW_SRC1 0x0800000 +#define SLOW_SRC2 0x1000000 + +static int emit_op_imm(struct sljit_compiler *compiler, int flags, int dst, sljit_uw arg1, sljit_uw arg2) +{ + /* dst must be register, TMP_REG1 + arg1 must be register, TMP_REG1, imm + arg2 must be register, TMP_REG2, imm */ + int reg; + sljit_uw imm; + + if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) { + /* Both are immediates. */ + flags &= ~ARG1_IMM; + FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); + arg1 = TMP_REG1; + } + + if (flags & (ARG1_IMM | ARG2_IMM)) { + reg = (flags & ARG2_IMM) ? arg1 : arg2; + imm = (flags & ARG2_IMM) ? arg2 : arg1; + + switch (flags & 0xffff) { + case SLJIT_MOV: + SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1); + return load_immediate(compiler, dst, imm); + case SLJIT_NOT: + if (!(flags & SET_FLAGS)) + return load_immediate(compiler, dst, ~imm); + /* Since the flags should be set, we just fallback to the register mode. + Although I could do some clever things here, "NOT IMM" does not worth the efforts. */ + break; + case SLJIT_CLZ: + /* No form with immediate operand. */ + break; + case SLJIT_ADD: + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { + if (imm <= 0x7) + return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); + if (reg == dst && imm <= 0xff) + return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst)); + } + if (imm <= 0xfff && !(flags & SET_FLAGS)) + return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm)); + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + break; + case SLJIT_ADDC: + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + break; + case SLJIT_SUB: + if (flags & ARG2_IMM) { + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(reg, dst)) { + if (imm <= 0x7) + return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); + if (imm <= 0xff) { + if (reg == dst) + return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst)); + if (flags & UNUSED_RETURN) + return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg)); + } + } + if (imm <= 0xfff && !(flags & SET_FLAGS)) + return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm)); + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + } + else { + if (!(flags & KEEP_FLAGS) && imm == 0 && IS_2_LO_REGS(reg, dst)) + return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg)); + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + } + break; + case SLJIT_SUBC: + if (flags & ARG2_IMM) { + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + } + break; + case SLJIT_MUL: + /* No form with immediate operand. */ + break; + case SLJIT_AND: + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1)); + if (imm != INVALID_IMM) + return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + break; + case SLJIT_OR: + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + imm = get_imm(~((flags & ARG2_IMM) ? arg2 : arg1)); + if (imm != INVALID_IMM) + return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + break; + case SLJIT_XOR: + imm = get_imm(imm); + if (imm != INVALID_IMM) + return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm); + break; + case SLJIT_SHL: + if (flags & ARG2_IMM) { + imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6)); + return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); + } + break; + case SLJIT_LSHR: + if (flags & ARG2_IMM) { + imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6)); + return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); + } + break; + case SLJIT_ASHR: + if (flags & ARG2_IMM) { + imm &= 0x1f; + if (imm == 0) { + if (!(flags & SET_FLAGS)) + return push_inst16(compiler, MOV | SET_REGS44(dst, reg)); + if (IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg)); + return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg)); + } + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, reg)) + return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6)); + return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm)); + } + break; + default: + SLJIT_ASSERT_STOP(); + break; + } + + if (flags & ARG2_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG2, arg2)); + arg2 = TMP_REG2; + } + else { + FAIL_IF(load_immediate(compiler, TMP_REG1, arg1)); + arg1 = TMP_REG1; + } + } + + /* Both arguments are registers. */ + switch (flags & 0xffff) { + case SLJIT_MOV: + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + case SLJIT_MOVU: + case SLJIT_MOVU_UI: + case SLJIT_MOVU_SI: + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + return push_inst16(compiler, MOV | SET_REGS44(dst, arg2)); + case SLJIT_MOV_UB: + case SLJIT_MOVU_UB: + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + if (IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2)); + case SLJIT_MOV_SB: + case SLJIT_MOVU_SB: + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + if (IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2)); + case SLJIT_MOV_UH: + case SLJIT_MOVU_UH: + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + if (IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2)); + case SLJIT_MOV_SH: + case SLJIT_MOVU_SH: + SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1); + if (IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2)); + case SLJIT_NOT: + SLJIT_ASSERT(arg1 == TMP_REG1); + if (!(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, MVNS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(arg2)); + case SLJIT_CLZ: + SLJIT_ASSERT(arg1 == TMP_REG1); + FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2))); + if (flags & SET_FLAGS) { + if (reg_map[dst] <= 7) + return push_inst16(compiler, CMPI | RDN3(dst)); + return push_inst32(compiler, ADD_WI | SET_FLAGS | RN4(dst) | RD4(dst)); + } + return SLJIT_SUCCESS; + case SLJIT_ADD: + if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2)) + return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2)); + if (dst == arg1 && !(flags & SET_FLAGS)) + return push_inst16(compiler, ADD | SET_REGS44(dst, arg2)); + return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_ADDC: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_SUB: + if (!(flags & KEEP_FLAGS) && IS_3_LO_REGS(dst, arg1, arg2)) + return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2)); + return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_SUBC: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_MUL: + if (!(flags & SET_FLAGS)) + return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2)); + SLJIT_ASSERT(reg_map[TMP_REG2] <= 7 && dst != TMP_REG2); + FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(TMP_REG2) | RN4(arg1) | RM4(arg2))); + /* cmp TMP_REG2, dst asr #31. */ + return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst)); + case SLJIT_AND: + if (!(flags & KEEP_FLAGS)) { + if (dst == arg1 && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2)); + if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2)) + return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2)); + } + return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_OR: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_XOR: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_SHL: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_LSHR: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + case SLJIT_ASHR: + if (dst == arg1 && !(flags & KEEP_FLAGS) && IS_2_LO_REGS(dst, arg2)) + return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2)); + return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2)); + } + + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; +} + +#define STORE 0x01 +#define SIGNED 0x02 + +#define WORD_SIZE 0x00 +#define BYTE_SIZE 0x04 +#define HALF_SIZE 0x08 + +#define UPDATE 0x10 +#define ARG_TEST 0x20 + +#define IS_WORD_SIZE(flags) (!(flags & (BYTE_SIZE | HALF_SIZE))) +#define OFFSET_CHECK(imm, shift) (!(argw & ~(imm << shift))) + +/* + 1st letter: + w = word + b = byte + h = half + + 2nd letter: + s = signed + u = unsigned + + 3rd letter: + l = load + s = store +*/ + +static SLJIT_CONST sljit_uw sljit_mem16[12] = { +/* w u l */ 0x5800 /* ldr */, +/* w u s */ 0x5000 /* str */, +/* w s l */ 0x5800 /* ldr */, +/* w s s */ 0x5000 /* str */, + +/* b u l */ 0x5c00 /* ldrb */, +/* b u s */ 0x5400 /* strb */, +/* b s l */ 0x5600 /* ldrsb */, +/* b s s */ 0x5400 /* strb */, + +/* h u l */ 0x5a00 /* ldrh */, +/* h u s */ 0x5200 /* strh */, +/* h s l */ 0x5e00 /* ldrsh */, +/* h s s */ 0x5200 /* strh */, +}; + +static SLJIT_CONST sljit_uw sljit_mem16_imm5[12] = { +/* w u l */ 0x6800 /* ldr imm5 */, +/* w u s */ 0x6000 /* str imm5 */, +/* w s l */ 0x6800 /* ldr imm5 */, +/* w s s */ 0x6000 /* str imm5 */, + +/* b u l */ 0x7800 /* ldrb imm5 */, +/* b u s */ 0x7000 /* strb imm5 */, +/* b s l */ 0x0000 /* not allowed */, +/* b s s */ 0x7000 /* strb imm5 */, + +/* h u l */ 0x8800 /* ldrh imm5 */, +/* h u s */ 0x8000 /* strh imm5 */, +/* h s l */ 0x0000 /* not allowed */, +/* h s s */ 0x8000 /* strh imm5 */, +}; + +#define MEM_IMM8 0xc00 +#define MEM_IMM12 0x800000 +static SLJIT_CONST sljit_uw sljit_mem32[12] = { +/* w u l */ 0xf8500000 /* ldr.w */, +/* w u s */ 0xf8400000 /* str.w */, +/* w s l */ 0xf8500000 /* ldr.w */, +/* w s s */ 0xf8400000 /* str.w */, + +/* b u l */ 0xf8100000 /* ldrb.w */, +/* b u s */ 0xf8000000 /* strb.w */, +/* b s l */ 0xf9100000 /* ldrsb.w */, +/* b s s */ 0xf8000000 /* strb.w */, + +/* h u l */ 0xf8300000 /* ldrh.w */, +/* h u s */ 0xf8200000 /* strsh.w */, +/* h s l */ 0xf9300000 /* ldrsh.w */, +/* h s s */ 0xf8200000 /* strsh.w */, +}; + +/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */ +static int emit_set_delta(struct sljit_compiler *compiler, int dst, int reg, sljit_w value) +{ + if (value >= 0) { + if (value <= 0xfff) + return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value)); + value = get_imm(value); + if (value != INVALID_IMM) + return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | value); + } + else { + value = -value; + if (value <= 0xfff) + return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value)); + value = get_imm(value); + if (value != INVALID_IMM) + return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | value); + } + return SLJIT_ERR_UNSUPPORTED; +} + +/* Can perform an operation using at most 1 instruction. */ +static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw) +{ + int tmp; + + SLJIT_ASSERT(arg & SLJIT_MEM); + + if (SLJIT_UNLIKELY(flags & UPDATE)) { + if ((arg & 0xf) && !(arg & 0xf0) && argw <= 0xff && argw >= -0xff) { + flags &= ~UPDATE; + arg &= 0xf; + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + + if (argw >= 0) + argw |= 0x200; + else { + argw = -argw; + } + SLJIT_ASSERT(argw >= 0 && (argw & 0xff) <= 0xff); + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | 0x100 | argw)); + return -1; + } + return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0; + } + + if (SLJIT_UNLIKELY(arg & 0xf0)) { + argw &= 0x3; + tmp = (arg >> 4) & 0xf; + arg &= 0xf; + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + + if (!argw && IS_3_LO_REGS(reg, arg, tmp)) + FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp))); + else + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4))); + return -1; + } + + if (!(arg & 0xf) || argw > 0xfff || argw < -0xff) + return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0; + + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + + arg &= 0xf; + if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) { + tmp = 3; + if (IS_WORD_SIZE(flags)) { + if (OFFSET_CHECK(0x1f, 2)) + tmp = 2; + } + else if (flags & BYTE_SIZE) + { + if (OFFSET_CHECK(0x1f, 0)) + tmp = 0; + } + else { + SLJIT_ASSERT(flags & HALF_SIZE); + if (OFFSET_CHECK(0x1f, 1)) + tmp = 1; + } + + if (tmp != 3) { + FAIL_IF(push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp)))); + return -1; + } + } + + /* SP based immediate. */ + if (SLJIT_UNLIKELY(arg == SLJIT_LOCALS_REG) && OFFSET_CHECK(0xff, 2) && IS_WORD_SIZE(flags) && reg_map[reg] <= 7) { + FAIL_IF(push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2))); + return -1; + } + + if (argw >= 0) + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw)); + else + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw)); + return -1; +} + +/* see getput_arg below. + Note: can_cache is called only for binary operators. Those + operators always uses word arguments without write back. */ +static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + /* Simple operation except for updates. */ + if ((arg & 0xf0) || !(next_arg & SLJIT_MEM)) + return 0; + + if (!(arg & 0xf)) { + if ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff) + return 1; + return 0; + } + + if (argw == next_argw) + return 1; + + if (arg == next_arg && ((sljit_uw)(argw - next_argw) <= 0xfff || (sljit_uw)(next_argw - argw) <= 0xfff)) + return 1; + + return 0; +} + +/* Emit the necessary instructions. See can_cache above. */ +static int getput_arg(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + int tmp_r; + sljit_w tmp; + + SLJIT_ASSERT(arg & SLJIT_MEM); + if (!(next_arg & SLJIT_MEM)) { + next_arg = 0; + next_argw = 0; + } + + tmp_r = (flags & STORE) ? TMP_REG3 : reg; + + if (SLJIT_UNLIKELY(flags & UPDATE)) { + flags &= ~UPDATE; + /* Update only applies if a base register exists. */ + if (arg & 0xf) { + /* There is no caching here. */ + tmp = (arg & 0xf0) >> 4; + arg &= 0xf; + + if (!tmp) { + if (!(argw & ~0xfff)) { + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw)); + return push_inst32(compiler, ADDWI | RD4(arg) | RN4(arg) | IMM12(argw)); + } + + if (compiler->cache_arg == SLJIT_MEM) { + if (argw == compiler->cache_argw) { + tmp = TMP_REG3; + argw = 0; + } + else if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { + FAIL_IF(compiler->error); + compiler->cache_argw = argw; + tmp = TMP_REG3; + argw = 0; + } + } + + if (argw) { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + compiler->cache_arg = SLJIT_MEM; + compiler->cache_argw = argw; + tmp = TMP_REG3; + argw = 0; + } + } + + argw &= 0x3; + if (!argw && IS_3_LO_REGS(reg, arg, tmp)) { + FAIL_IF(push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp))); + return push_inst16(compiler, ADD | SET_REGS44(arg, tmp)); + } + FAIL_IF(push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp) | (argw << 4))); + return push_inst32(compiler, ADD_W | RD4(arg) | RN4(arg) | RM4(tmp) | (argw << 6)); + } + } + + SLJIT_ASSERT(!(arg & 0xf0)); + + if (compiler->cache_arg == arg) { + if (!((argw - compiler->cache_argw) & ~0xfff)) + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | (argw - compiler->cache_argw)); + if (!((compiler->cache_argw - argw) & ~0xff)) + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(TMP_REG3) | (compiler->cache_argw - argw)); + if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, argw - compiler->cache_argw) != SLJIT_ERR_UNSUPPORTED) { + FAIL_IF(compiler->error); + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); + } + } + + next_arg = (arg & 0xf) && (arg == next_arg); + arg &= 0xf; + if (arg && compiler->cache_arg == SLJIT_MEM && compiler->cache_argw == argw) + return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3)); + + compiler->cache_argw = argw; + if (next_arg && emit_set_delta(compiler, TMP_REG3, arg, argw) != SLJIT_ERR_UNSUPPORTED) { + FAIL_IF(compiler->error); + compiler->cache_arg = SLJIT_MEM | arg; + arg = 0; + } + else { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + compiler->cache_arg = SLJIT_MEM; + + if (next_arg) { + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, arg))); + compiler->cache_arg = SLJIT_MEM | arg; + arg = 0; + } + } + + if (arg) + return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(TMP_REG3)); + return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(TMP_REG3) | 0); +} + +static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw) +{ + if (getput_arg_fast(compiler, flags, reg, arg, argw)) + return compiler->error; + compiler->cache_arg = 0; + compiler->cache_argw = 0; + return getput_arg(compiler, flags, reg, arg, argw, 0, 0); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size; + sljit_ins push; + + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + push = (1 << 4); + if (saveds >= 5) + push |= 1 << 11; + if (saveds >= 4) + push |= 1 << 10; + if (saveds >= 3) + push |= 1 << 8; + if (saveds >= 2) + push |= 1 << 7; + if (saveds >= 1) + push |= 1 << 6; + if (temporaries >= 5) + push |= 1 << 5; + FAIL_IF(saveds >= 3 + ? push_inst32(compiler, PUSH_W | (1 << 14) | push) + : push_inst16(compiler, PUSH | push)); + + /* Stack must be aligned to 8 bytes: */ + size = (3 + saveds) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; + if (local_size > 0) { + if (local_size <= (127 << 2)) + FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2))); + else + FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, local_size)); + } + + if (args >= 1) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG1, SLJIT_TEMPORARY_REG1))); + if (args >= 2) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG2, SLJIT_TEMPORARY_REG2))); + if (args >= 3) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SAVED_REG3, SLJIT_TEMPORARY_REG3))); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size; + + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + size = (3 + saveds) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + sljit_ins pop; + + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + if (compiler->local_size > 0) { + if (compiler->local_size <= (127 << 2)) + FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2))); + else + FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_LOCALS_REG, SLJIT_LOCALS_REG, compiler->local_size)); + } + + pop = (1 << 4); + if (compiler->saveds >= 5) + pop |= 1 << 11; + if (compiler->saveds >= 4) + pop |= 1 << 10; + if (compiler->saveds >= 3) + pop |= 1 << 8; + if (compiler->saveds >= 2) + pop |= 1 << 7; + if (compiler->saveds >= 1) + pop |= 1 << 6; + if (compiler->temporaries >= 5) + pop |= 1 << 5; + return compiler->saveds >= 3 + ? push_inst32(compiler, POP_W | (1 << 15) | pop) + : push_inst16(compiler, POP | pop); +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) +extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator); +extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator); +#else +#error "Software divmod functions are needed" +#endif + +#ifdef __cplusplus +} +#endif + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + CHECK_ERROR(); + check_sljit_emit_op0(compiler, op); + + op = GET_OPCODE(op); + switch (op) { + case SLJIT_BREAKPOINT: + push_inst16(compiler, BKPT); + break; + case SLJIT_NOP: + push_inst16(compiler, NOP); + break; + case SLJIT_UMUL: + case SLJIT_SMUL: + return push_inst32(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) + | (reg_map[SLJIT_TEMPORARY_REG2] << 8) + | (reg_map[SLJIT_TEMPORARY_REG1] << 12) + | (reg_map[SLJIT_TEMPORARY_REG1] << 16) + | reg_map[SLJIT_TEMPORARY_REG2]); + case SLJIT_UDIV: + case SLJIT_SDIV: + if (compiler->temporaries >= 4) { + FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); + FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); + } else if (compiler->temporaries >= 3) + FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); +#if defined(__GNUC__) + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, + (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); +#else +#error "Software divmod functions are needed" +#endif + if (compiler->temporaries >= 4) { + FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); + return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); + } else if (compiler->temporaries >= 3) + return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int op_type, dst_r, flags; + + CHECK_ERROR(); + check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + op_type = GET_OPCODE(op); + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; + + if (op_type >= SLJIT_MOV && op_type <= SLJIT_MOVU_SI) { + switch (op_type) { + case SLJIT_MOV: + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + flags = WORD_SIZE; + break; + case SLJIT_MOV_UB: + flags = BYTE_SIZE; + if (src & SLJIT_IMM) + srcw = (unsigned char)srcw; + break; + case SLJIT_MOV_SB: + flags = BYTE_SIZE | SIGNED; + if (src & SLJIT_IMM) + srcw = (signed char)srcw; + break; + case SLJIT_MOV_UH: + flags = HALF_SIZE; + if (src & SLJIT_IMM) + srcw = (unsigned short)srcw; + break; + case SLJIT_MOV_SH: + flags = HALF_SIZE | SIGNED; + if (src & SLJIT_IMM) + srcw = (signed short)srcw; + break; + case SLJIT_MOVU: + case SLJIT_MOVU_UI: + case SLJIT_MOVU_SI: + flags = WORD_SIZE | UPDATE; + break; + case SLJIT_MOVU_UB: + flags = BYTE_SIZE | UPDATE; + if (src & SLJIT_IMM) + srcw = (unsigned char)srcw; + break; + case SLJIT_MOVU_SB: + flags = BYTE_SIZE | SIGNED | UPDATE; + if (src & SLJIT_IMM) + srcw = (signed char)srcw; + break; + case SLJIT_MOVU_UH: + flags = HALF_SIZE | UPDATE; + if (src & SLJIT_IMM) + srcw = (unsigned short)srcw; + break; + case SLJIT_MOVU_SH: + flags = HALF_SIZE | SIGNED | UPDATE; + if (src & SLJIT_IMM) + srcw = (signed short)srcw; + break; + default: + SLJIT_ASSERT_STOP(); + flags = 0; + break; + } + + if (src & SLJIT_IMM) + FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw)); + else if (src & SLJIT_MEM) { + if (getput_arg_fast(compiler, flags, dst_r, src, srcw)) + FAIL_IF(compiler->error); + else + FAIL_IF(getput_arg(compiler, flags, dst_r, src, srcw, dst, dstw)); + } else { + if (dst_r != TMP_REG1) + return emit_op_imm(compiler, op_type, dst_r, TMP_REG1, src); + dst_r = src; + } + + if (dst & SLJIT_MEM) { + if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) + return compiler->error; + else + return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); + } + return SLJIT_SUCCESS; + } + + if (op_type == SLJIT_NEG) { +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, GET_FLAGS(op) | SLJIT_SUB, dst, dstw, SLJIT_IMM, 0, src, srcw); + } + + flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); + if (src & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src, srcw)) + FAIL_IF(compiler->error); + else + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, dst, dstw)); + src = TMP_REG2; + } + + if (src & SLJIT_IMM) + flags |= ARG2_IMM; + else + srcw = src; + + emit_op_imm(compiler, flags | op_type, dst_r, TMP_REG1, srcw); + + if (dst & SLJIT_MEM) { + if (getput_arg_fast(compiler, flags | STORE, dst_r, dst, dstw)) + return compiler->error; + else + return getput_arg(compiler, flags | STORE, dst_r, dst, dstw, 0, 0); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_r, flags; + + CHECK_ERROR(); + check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; + flags = (GET_FLAGS(op) ? SET_FLAGS : 0) | ((op & SLJIT_KEEP_FLAGS) ? KEEP_FLAGS : 0); + + if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, WORD_SIZE | STORE | ARG_TEST, TMP_REG1, dst, dstw)) + flags |= SLOW_DEST; + + if (src1 & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG1, src1, src1w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC1; + } + if (src2 & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG2, src2, src2w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC2; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG1, src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src2, src2w, dst, dstw)); + + if (src1 & SLJIT_MEM) + src1 = TMP_REG1; + if (src2 & SLJIT_MEM) + src2 = TMP_REG2; + + if (src1 & SLJIT_IMM) + flags |= ARG1_IMM; + else + src1w = src1; + if (src2 & SLJIT_IMM) + flags |= ARG2_IMM; + else + src2w = src2; + + if (dst == SLJIT_UNUSED) + flags |= UNUSED_RETURN; + + if (GET_OPCODE(op) == SLJIT_MUL && (op & SLJIT_SET_O)) + flags |= SET_MULOV; + + emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w); + + if (dst & SLJIT_MEM) { + if (!(flags & SLOW_DEST)) { + getput_arg_fast(compiler, WORD_SIZE | STORE, dst_r, dst, dstw); + return compiler->error; + } + return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, 0, 0); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + check_sljit_get_register_index(reg); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + CHECK_ERROR(); + check_sljit_emit_op_custom(compiler, instruction, size); + SLJIT_ASSERT(size == 2 || size == 4); + + if (size == 2) + return push_inst16(compiler, *(sljit_uh*)instruction); + return push_inst32(compiler, *(sljit_ins*)instruction); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + return 1; +} + +static int emit_fop_mem(struct sljit_compiler *compiler, int flags, int reg, int arg, sljit_w argw) +{ + sljit_w tmp; + sljit_w inst = VSTR | ((flags & STORE) ? 0 : 0x00100000); + + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* Fast loads and stores. */ + if (SLJIT_UNLIKELY(arg & 0xf0)) { + FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG2) | RN4(arg & 0xf) | RM4((arg & 0xf0) >> 4) | ((argw & 0x3) << 6))); + arg = SLJIT_MEM | TMP_REG2; + argw = 0; + } + + if (arg & 0xf) { + if (!(argw & ~0x3fc)) + return push_inst32(compiler, inst | 0x800000 | RN4(arg & 0xf) | DD4(reg) | (argw >> 2)); + if (!(-argw & ~0x3fc)) + return push_inst32(compiler, inst | RN4(arg & 0xf) | DD4(reg) | (-argw >> 2)); + } + + SLJIT_ASSERT(!(arg & 0xf0)); + if (compiler->cache_arg == arg) { + tmp = argw - compiler->cache_argw; + if (!(tmp & ~0x3fc)) + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg) | (tmp >> 2)); + if (!(-tmp & ~0x3fc)) + return push_inst32(compiler, inst | RN4(TMP_REG3) | DD4(reg) | (-tmp >> 2)); + if (emit_set_delta(compiler, TMP_REG3, TMP_REG3, tmp) != SLJIT_ERR_UNSUPPORTED) { + FAIL_IF(compiler->error); + compiler->cache_argw = argw; + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); + } + } + + compiler->cache_arg = arg; + compiler->cache_argw = argw; + + if (SLJIT_UNLIKELY(!(arg & 0xf))) + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + else if (emit_set_delta(compiler, TMP_REG3, arg & 0xf, argw) != SLJIT_ERR_UNSUPPORTED) + FAIL_IF(compiler->error); + else { + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + if (arg & 0xf) + FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG3, (arg & 0xf)))); + } + return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG3) | DD4(reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int dst_r; + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (GET_OPCODE(op) == SLJIT_FCMP) { + if (dst & SLJIT_MEM) { + emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw); + dst = TMP_FREG1; + } + if (src & SLJIT_MEM) { + emit_fop_mem(compiler, 0, TMP_FREG2, src, srcw); + src = TMP_FREG2; + } + FAIL_IF(push_inst32(compiler, VCMP_F64 | DD4(dst) | DM4(src))); + return push_inst32(compiler, VMRS); + } + + dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1; + if (src & SLJIT_MEM) { + emit_fop_mem(compiler, 0, dst_r, src, srcw); + src = dst_r; + } + + switch (GET_OPCODE(op)) { + case SLJIT_FMOV: + if (src != dst_r) + FAIL_IF(push_inst32(compiler, VMOV_F64 | DD4(dst_r) | DM4(src))); + break; + case SLJIT_FNEG: + FAIL_IF(push_inst32(compiler, VNEG_F64 | DD4(dst_r) | DM4(src))); + break; + case SLJIT_FABS: + FAIL_IF(push_inst32(compiler, VABS_F64 | DD4(dst_r) | DM4(src))); + break; + } + + if (dst & SLJIT_MEM) + return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_r; + + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_r = (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? dst : TMP_FREG1; + if (src1 & SLJIT_MEM) { + emit_fop_mem(compiler, 0, TMP_FREG1, src1, src1w); + src1 = TMP_FREG1; + } + if (src2 & SLJIT_MEM) { + emit_fop_mem(compiler, 0, TMP_FREG2, src2, src2w); + src2 = TMP_FREG2; + } + + switch (GET_OPCODE(op)) { + case SLJIT_FADD: + FAIL_IF(push_inst32(compiler, VADD_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); + break; + case SLJIT_FSUB: + FAIL_IF(push_inst32(compiler, VSUB_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); + break; + case SLJIT_FMUL: + FAIL_IF(push_inst32(compiler, VMUL_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); + break; + case SLJIT_FDIV: + FAIL_IF(push_inst32(compiler, VDIV_F64 | DD4(dst_r) | DN4(src1) | DM4(src2))); + break; + } + + if (dst & SLJIT_MEM) + return emit_fop_mem(compiler, STORE, TMP_FREG1, dst, dstw); + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + int size; + + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + size = (3 + saveds) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG3)); + else if (dst & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_SIZE | STORE, TMP_REG3, dst, dstw)) + return compiler->error; + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, TMP_REG3))); + compiler->cache_arg = 0; + compiler->cache_argw = 0; + return getput_arg(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, 0, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, src))); + else if (src & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_SIZE, TMP_REG3, src, srcw)) + FAIL_IF(compiler->error); + else { + compiler->cache_arg = 0; + compiler->cache_argw = 0; + FAIL_IF(getput_arg(compiler, WORD_SIZE, TMP_REG2, src, srcw, 0, 0)); + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG3, TMP_REG2))); + } + } + else if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, TMP_REG3, srcw)); + return push_inst16(compiler, BLX | RN3(TMP_REG3)); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +static sljit_uw get_cc(int type) +{ + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_C_FLOAT_EQUAL: + return 0x0; + + case SLJIT_C_NOT_EQUAL: + case SLJIT_C_MUL_OVERFLOW: + case SLJIT_C_FLOAT_NOT_EQUAL: + return 0x1; + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + return 0x3; + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + return 0x2; + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + return 0x8; + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + return 0x9; + + case SLJIT_C_SIG_LESS: + return 0xb; + + case SLJIT_C_SIG_GREATER_EQUAL: + return 0xa; + + case SLJIT_C_SIG_GREATER: + return 0xc; + + case SLJIT_C_SIG_LESS_EQUAL: + return 0xd; + + case SLJIT_C_OVERFLOW: + case SLJIT_C_FLOAT_NAN: + return 0x6; + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_FLOAT_NOT_NAN: + return 0x7; + + default: /* SLJIT_JUMP */ + return 0xe; + } +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + check_sljit_emit_label(compiler); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + struct sljit_jump *jump; + int cc; + + CHECK_ERROR_PTR(); + check_sljit_emit_jump(compiler, type); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + /* In ARM, we don't need to touch the arguments. */ + PTR_FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); + if (type < SLJIT_JUMP) { + jump->flags |= IS_CONDITIONAL; + cc = get_cc(type); + jump->flags |= cc << 8; + PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); + } + + jump->addr = compiler->size; + if (type <= SLJIT_JUMP) + PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1))); + else { + jump->flags |= IS_BL; + PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1))); + } + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + struct sljit_jump *jump; + + CHECK_ERROR(); + check_sljit_emit_ijump(compiler, type, src, srcw); + + /* In ARM, we don't need to touch the arguments. */ + if (src & SLJIT_IMM) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); + jump->u.target = srcw; + + FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0)); + jump->addr = compiler->size; + FAIL_IF(push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1))); + } + else { + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src)); + + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw)); + if (type >= SLJIT_FAST_CALL) + return push_inst16(compiler, BLX | RN3(TMP_REG1)); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + int dst_r; + sljit_uw cc; + + CHECK_ERROR(); + check_sljit_emit_cond_value(compiler, op, dst, dstw, type); + + if (dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + cc = get_cc(type); + if (GET_OPCODE(op) == SLJIT_OR && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8)); + FAIL_IF(push_inst32(compiler, ORRI | RN4(dst) | RD4(dst) | 0x1)); + if (op & SLJIT_SET_E) { + if (reg_map[dst] <= 7) + return push_inst16(compiler, ORRS | RD3(dst) | RN3(dst)); + return push_inst32(compiler, ORR_W | SET_FLAGS | RD4(TMP_REG1) | RN4(dst) | RM4(dst)); + } + return SLJIT_SUCCESS; + } + + dst_r = TMP_REG2; + if (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && reg_map[dst] <= 7) + dst_r = dst; + + FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4)); + FAIL_IF(push_inst16(compiler, MOVSI | 0x1 | RDN3(dst_r))); + FAIL_IF(push_inst16(compiler, MOVSI | 0x0 | RDN3(dst_r))); + + if (dst_r == TMP_REG2) { + if (GET_OPCODE(op) == SLJIT_OR) { +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REG2, 0); + } + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw); + else + return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2)); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + struct sljit_const *const_; + int dst_r; + + CHECK_ERROR_PTR(); + check_sljit_emit_const(compiler, dst, dstw, init_value); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG1; + PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value)); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw)); + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + inline_set_jump_addr(addr, new_addr, 1); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + sljit_uh* inst = (sljit_uh*)addr; + modify_imm32_const(inst, new_constant); + SLJIT_CACHE_FLUSH(inst, inst + 3); +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c b/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c new file mode 100644 index 0000000000..e3a5873247 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_v5.c @@ -0,0 +1,2424 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + return "ARMv7" SLJIT_CPUINFO; +#elif (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + return "ARMv5" SLJIT_CPUINFO; +#else +#error "Internal error: Unknown ARM architecture" +#endif +} + +/* Last register + 1. */ +#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) +#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) +#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) +#define TMP_PC (SLJIT_NO_REGISTERS + 4) + +#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) +#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2) + +/* In ARM instruction words. + Cache lines are usually 32 byte aligned. */ +#define CONST_POOL_ALIGNMENT 8 +#define CONST_POOL_EMPTY 0xffffffff + +#define ALIGN_INSTRUCTION(ptr) \ + (sljit_uw*)(((sljit_uw)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_uw)) - 1)) +#define MAX_DIFFERENCE(max_diff) \ + (((max_diff) / (int)sizeof(sljit_uw)) - (CONST_POOL_ALIGNMENT - 1)) + +/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */ +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { + 0, 0, 1, 2, 10, 11, 4, 5, 6, 7, 8, 13, 3, 12, 14, 15 +}; + +#define RM(rm) (reg_map[rm]) +#define RD(rd) (reg_map[rd] << 12) +#define RN(rn) (reg_map[rn] << 16) + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ + +/* The instruction includes the AL condition. + INST_NAME - CONDITIONAL remove this flag. */ +#define COND_MASK 0xf0000000 +#define CONDITIONAL 0xe0000000 +#define PUSH_POOL 0xff000000 + +/* DP - Data Processing instruction (use with EMIT_DATA_PROCESS_INS). */ +#define ADC_DP 0x5 +#define ADD_DP 0x4 +#define AND_DP 0x0 +#define B 0xea000000 +#define BIC_DP 0xe +#define BL 0xeb000000 +#define BLX 0xe12fff30 +#define BX 0xe12fff10 +#define CLZ 0xe16f0f10 +#define CMP_DP 0xa +#define BKPT 0xe1200070 +#define EOR_DP 0x1 +#define MOV_DP 0xd +#define MUL 0xe0000090 +#define MVN_DP 0xf +#define NOP 0xe1a00000 +#define ORR_DP 0xc +#define PUSH 0xe92d0000 +#define POP 0xe8bd0000 +#define RSB_DP 0x3 +#define RSC_DP 0x7 +#define SBC_DP 0x6 +#define SMULL 0xe0c00090 +#define SUB_DP 0x2 +#define UMULL 0xe0800090 +#define VABS_F64 0xeeb00bc0 +#define VADD_F64 0xee300b00 +#define VCMP_F64 0xeeb40b40 +#define VDIV_F64 0xee800b00 +#define VMOV_F64 0xeeb00b40 +#define VMRS 0xeef1fa10 +#define VMUL_F64 0xee200b00 +#define VNEG_F64 0xeeb10b40 +#define VSTR 0xed000b00 +#define VSUB_F64 0xee300b40 + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) +/* Arm v7 specific instructions. */ +#define MOVW 0xe3000000 +#define MOVT 0xe3400000 +#define SXTB 0xe6af0070 +#define SXTH 0xe6bf0070 +#define UXTB 0xe6ef0070 +#define UXTH 0xe6ff0070 +#endif + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + +static int push_cpool(struct sljit_compiler *compiler) +{ + /* Pushing the constant pool into the instruction stream. */ + sljit_uw* inst; + sljit_uw* cpool_ptr; + sljit_uw* cpool_end; + int i; + + /* The label could point the address after the constant pool. */ + if (compiler->last_label && compiler->last_label->size == compiler->size) + compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1; + + SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE); + inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!inst); + compiler->size++; + *inst = 0xff000000 | compiler->cpool_fill; + + for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) { + inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!inst); + compiler->size++; + *inst = 0; + } + + cpool_ptr = compiler->cpool; + cpool_end = cpool_ptr + compiler->cpool_fill; + while (cpool_ptr < cpool_end) { + inst = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!inst); + compiler->size++; + *inst = *cpool_ptr++; + } + compiler->cpool_diff = CONST_POOL_EMPTY; + compiler->cpool_fill = 0; + return SLJIT_SUCCESS; +} + +static int push_inst(struct sljit_compiler *compiler, sljit_uw inst) +{ + sljit_uw* ptr; + + if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092))) + FAIL_IF(push_cpool(compiler)); + + ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!ptr); + compiler->size++; + *ptr = inst; + return SLJIT_SUCCESS; +} + +static int push_inst_with_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) +{ + sljit_uw* ptr; + sljit_uw cpool_index = CPOOL_SIZE; + sljit_uw* cpool_ptr; + sljit_uw* cpool_end; + sljit_ub* cpool_unique_ptr; + + if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092))) + FAIL_IF(push_cpool(compiler)); + else if (compiler->cpool_fill > 0) { + cpool_ptr = compiler->cpool; + cpool_end = cpool_ptr + compiler->cpool_fill; + cpool_unique_ptr = compiler->cpool_unique; + do { + if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) { + cpool_index = cpool_ptr - compiler->cpool; + break; + } + cpool_ptr++; + cpool_unique_ptr++; + } while (cpool_ptr < cpool_end); + } + + if (cpool_index == CPOOL_SIZE) { + /* Must allocate a new entry in the literal pool. */ + if (compiler->cpool_fill < CPOOL_SIZE) { + cpool_index = compiler->cpool_fill; + compiler->cpool_fill++; + } + else { + FAIL_IF(push_cpool(compiler)); + cpool_index = 0; + compiler->cpool_fill = 1; + } + } + + SLJIT_ASSERT((inst & 0xfff) == 0); + ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!ptr); + compiler->size++; + *ptr = inst | cpool_index; + + compiler->cpool[cpool_index] = literal; + compiler->cpool_unique[cpool_index] = 0; + if (compiler->cpool_diff == CONST_POOL_EMPTY) + compiler->cpool_diff = compiler->size; + return SLJIT_SUCCESS; +} + +static int push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_uw inst, sljit_uw literal) +{ + sljit_uw* ptr; + if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE)) + FAIL_IF(push_cpool(compiler)); + + SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0); + ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!ptr); + compiler->size++; + *ptr = inst | compiler->cpool_fill; + + compiler->cpool[compiler->cpool_fill] = literal; + compiler->cpool_unique[compiler->cpool_fill] = 1; + compiler->cpool_fill++; + if (compiler->cpool_diff == CONST_POOL_EMPTY) + compiler->cpool_diff = compiler->size; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int prepare_blx(struct sljit_compiler *compiler) +{ + /* Place for at least two instruction (doesn't matter whether the first has a literal). */ + if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088))) + return push_cpool(compiler); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_blx(struct sljit_compiler *compiler) +{ + /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */ + SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092)); + return push_inst(compiler, BLX | RM(TMP_REG1)); +} + +static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size) +{ + sljit_uw diff; + sljit_uw ind; + sljit_uw counter = 0; + sljit_uw* clear_const_pool = const_pool; + sljit_uw* clear_const_pool_end = const_pool + cpool_size; + + SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT); + /* Set unused flag for all literals in the constant pool. + I.e.: unused literals can belong to branches, which can be encoded as B or BL. + We can "compress" the constant pool by discarding these literals. */ + while (clear_const_pool < clear_const_pool_end) + *clear_const_pool++ = (sljit_uw)(-1); + + while (last_pc_patch < code_ptr) { + /* Data transfer instruction with Rn == r15. */ + if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) { + diff = const_pool - last_pc_patch; + ind = (*last_pc_patch) & 0xfff; + + /* Must be a load instruction with immediate offset. */ + SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20))); + if ((int)const_pool[ind] < 0) { + const_pool[ind] = counter; + ind = counter; + counter++; + } + else + ind = const_pool[ind]; + + SLJIT_ASSERT(diff >= 1); + if (diff >= 2 || ind > 0) { + diff = (diff + ind - 2) << 2; + SLJIT_ASSERT(diff <= 0xfff); + *last_pc_patch = (*last_pc_patch & ~0xfff) | diff; + } + else + *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004; + } + last_pc_patch++; + } + return counter; +} + +/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */ +struct future_patch { + struct future_patch* next; + int index; + int value; +}; + +static SLJIT_INLINE int resolve_const_pool_index(struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr) +{ + int value; + struct future_patch *curr_patch, *prev_patch; + + /* Using the values generated by patch_pc_relative_loads. */ + if (!*first_patch) + value = (int)cpool_start_address[cpool_current_index]; + else { + curr_patch = *first_patch; + prev_patch = 0; + while (1) { + if (!curr_patch) { + value = (int)cpool_start_address[cpool_current_index]; + break; + } + if ((sljit_uw)curr_patch->index == cpool_current_index) { + value = curr_patch->value; + if (prev_patch) + prev_patch->next = curr_patch->next; + else + *first_patch = curr_patch->next; + SLJIT_FREE(curr_patch); + break; + } + prev_patch = curr_patch; + curr_patch = curr_patch->next; + } + } + + if (value >= 0) { + if ((sljit_uw)value > cpool_current_index) { + curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch)); + if (!curr_patch) { + while (*first_patch) { + curr_patch = *first_patch; + *first_patch = (*first_patch)->next; + SLJIT_FREE(curr_patch); + } + return SLJIT_ERR_ALLOC_FAILED; + } + curr_patch->next = *first_patch; + curr_patch->index = value; + curr_patch->value = cpool_start_address[value]; + *first_patch = curr_patch; + } + cpool_start_address[value] = *buf_ptr; + } + return SLJIT_SUCCESS; +} + +#else + +static int push_inst(struct sljit_compiler *compiler, sljit_uw inst) +{ + sljit_uw* ptr; + + ptr = (sljit_uw*)ensure_buf(compiler, sizeof(sljit_uw)); + FAIL_IF(!ptr); + compiler->size++; + *ptr = inst; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_imm(struct sljit_compiler *compiler, int reg, sljit_w imm) +{ + FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff))); + return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff)); +} + +#endif + +static SLJIT_INLINE int detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code) +{ + sljit_w diff; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + return 0; + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (jump->flags & IS_BL) + code_ptr--; + + if (jump->flags & JUMP_ADDR) + diff = ((sljit_w)jump->u.target - (sljit_w)(code_ptr + 2)); + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)(code_ptr + 2)); + } + + /* Branch to Thumb code has not been optimized yet. */ + if (diff & 0x3) + return 0; + + diff >>= 2; + if (jump->flags & IS_BL) { + if (diff <= 0x01ffffff && diff >= -0x02000000) { + *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK); + jump->flags |= PATCH_B; + return 1; + } + } + else { + if (diff <= 0x01ffffff && diff >= -0x02000000) { + *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK); + jump->flags |= PATCH_B; + } + } +#else + if (jump->flags & JUMP_ADDR) + diff = ((sljit_w)jump->u.target - (sljit_w)code_ptr); + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + diff = ((sljit_w)(code + jump->u.label->size) - (sljit_w)code_ptr); + } + + /* Branch to Thumb code has not been optimized yet. */ + if (diff & 0x3) + return 0; + + diff >>= 2; + if (diff <= 0x01ffffff && diff >= -0x02000000) { + code_ptr -= 2; + *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (code_ptr[2] & COND_MASK); + jump->flags |= PATCH_B; + return 1; + } +#endif + return 0; +} + +static SLJIT_INLINE void inline_set_jump_addr(sljit_uw addr, sljit_uw new_addr, int flush) +{ +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_uw *ptr = (sljit_uw*)addr; + sljit_uw *inst = (sljit_uw*)ptr[0]; + sljit_uw mov_pc = ptr[1]; + int bl = (mov_pc & 0x0000f000) != RD(TMP_PC); + sljit_w diff = (sljit_w)(((sljit_w)new_addr - (sljit_w)(inst + 2)) >> 2); + + if (diff <= 0x7fffff && diff >= -0x800000) { + /* Turn to branch. */ + if (!bl) { + inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff); + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 1); + } + } else { + inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff); + inst[1] = NOP; + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 2); + } + } + } else { + /* Get the position of the constant. */ + if (mov_pc & (1 << 23)) + ptr = inst + ((mov_pc & 0xfff) >> 2) + 2; + else + ptr = inst + 1; + + if (*inst != mov_pc) { + inst[0] = mov_pc; + if (!bl) { + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 1); + } + } else { + inst[1] = BLX | RM(TMP_REG1); + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 2); + } + } + } + *ptr = new_addr; + } +#else + sljit_uw *inst = (sljit_uw*)addr; + SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); + inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff); + inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff); + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 2); + } +#endif +} + +static sljit_uw get_immediate(sljit_uw imm); + +static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_w new_constant, int flush) +{ +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_uw *ptr = (sljit_uw*)addr; + sljit_uw *inst = (sljit_uw*)ptr[0]; + sljit_uw ldr_literal = ptr[1]; + sljit_uw src2; + + src2 = get_immediate(new_constant); + if (src2) { + *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2; + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 1); + } + return; + } + + src2 = get_immediate(~new_constant); + if (src2) { + *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2; + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 1); + } + return; + } + + if (ldr_literal & (1 << 23)) + ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2; + else + ptr = inst + 1; + + if (*inst != ldr_literal) { + *inst = ldr_literal; + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 1); + } + } + *ptr = new_constant; +#else + sljit_uw *inst = (sljit_uw*)addr; + SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); + inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff); + inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff); + if (flush) { + SLJIT_CACHE_FLUSH(inst, inst + 2); + } +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_uw *code; + sljit_uw *code_ptr; + sljit_uw *buf_ptr; + sljit_uw *buf_end; + sljit_uw size; + sljit_uw word_count; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + sljit_uw cpool_size; + sljit_uw cpool_skip_alignment; + sljit_uw cpool_current_index; + sljit_uw *cpool_start_address; + sljit_uw *last_pc_patch; + struct future_patch *first_patch; +#endif + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + + CHECK_ERROR_PTR(); + check_sljit_generate_code(compiler); + reverse_buf(compiler); + + /* Second code generation pass. */ +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + size = compiler->size + (compiler->patches << 1); + if (compiler->cpool_fill > 0) + size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1; +#else + size = compiler->size; +#endif + code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw)); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + cpool_size = 0; + cpool_skip_alignment = 0; + cpool_current_index = 0; + cpool_start_address = NULL; + first_patch = NULL; + last_pc_patch = code; +#endif + + code_ptr = code; + word_count = 0; + + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + + if (label && label->size == 0) { + label->addr = (sljit_uw)code; + label->size = 0; + label = label->next; + } + + do { + buf_ptr = (sljit_uw*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 2); + do { + word_count++; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (cpool_size > 0) { + if (cpool_skip_alignment > 0) { + buf_ptr++; + cpool_skip_alignment--; + } + else { + if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { + SLJIT_FREE_EXEC(code); + compiler->error = SLJIT_ERR_ALLOC_FAILED; + return NULL; + } + buf_ptr++; + if (++cpool_current_index >= cpool_size) { + SLJIT_ASSERT(!first_patch); + cpool_size = 0; + if (label && label->size == word_count) { + /* Points after the current instruction. */ + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + } + } + } + else if ((*buf_ptr & 0xff000000) != PUSH_POOL) { +#endif + *code_ptr = *buf_ptr++; + /* These structures are ordered by their address. */ + SLJIT_ASSERT(!label || label->size >= word_count); + SLJIT_ASSERT(!jump || jump->addr >= word_count); + SLJIT_ASSERT(!const_ || const_->addr >= word_count); + if (jump && jump->addr == word_count) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (detect_jump_type(jump, code_ptr, code)) + code_ptr--; + jump->addr = (sljit_uw)code_ptr; +#else + jump->addr = (sljit_uw)(code_ptr - 2); + if (detect_jump_type(jump, code_ptr, code)) + code_ptr -= 2; +#endif + jump = jump->next; + } + if (label && label->size == word_count) { + /* code_ptr can be affected above. */ + label->addr = (sljit_uw)(code_ptr + 1); + label->size = (code_ptr + 1) - code; + label = label->next; + } + if (const_ && const_->addr == word_count) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + const_->addr = (sljit_uw)code_ptr; +#else + const_->addr = (sljit_uw)(code_ptr - 1); +#endif + const_ = const_->next; + } + code_ptr++; +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + } + else { + /* Fortunately, no need to shift. */ + cpool_size = *buf_ptr++ & ~PUSH_POOL; + SLJIT_ASSERT(cpool_size > 0); + cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1); + cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size); + if (cpool_current_index > 0) { + /* Unconditional branch. */ + *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL); + code_ptr = cpool_start_address + cpool_current_index; + } + cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1; + cpool_current_index = 0; + last_pc_patch = code_ptr; + } +#endif + } while (buf_ptr < buf_end); + buf = buf->next; + } while (buf); + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + SLJIT_ASSERT(cpool_size == 0); + if (compiler->cpool_fill > 0) { + cpool_start_address = ALIGN_INSTRUCTION(code_ptr); + cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill); + if (cpool_current_index > 0) + code_ptr = cpool_start_address + cpool_current_index; + + buf_ptr = compiler->cpool; + buf_end = buf_ptr + compiler->cpool_fill; + cpool_current_index = 0; + while (buf_ptr < buf_end) { + if (SLJIT_UNLIKELY(resolve_const_pool_index(&first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { + SLJIT_FREE_EXEC(code); + compiler->error = SLJIT_ERR_ALLOC_FAILED; + return NULL; + } + buf_ptr++; + cpool_current_index++; + } + SLJIT_ASSERT(!first_patch); + } +#endif + + jump = compiler->jumps; + while (jump) { + buf_ptr = (sljit_uw*)jump->addr; + + if (jump->flags & PATCH_B) { + if (!(jump->flags & JUMP_ADDR)) { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + SLJIT_ASSERT(((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >= -0x02000000); + *buf_ptr |= (((sljit_w)jump->u.label->addr - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff; + } + else { + SLJIT_ASSERT(((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) <= 0x01ffffff && ((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >= -0x02000000); + *buf_ptr |= (((sljit_w)jump->u.target - (sljit_w)(buf_ptr + 2)) >> 2) & 0x00ffffff; + } + } + else if (jump->flags & SLJIT_REWRITABLE_JUMP) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + jump->addr = (sljit_uw)code_ptr; + code_ptr[0] = (sljit_uw)buf_ptr; + code_ptr[1] = *buf_ptr; + inline_set_jump_addr((sljit_uw)code_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); + code_ptr += 2; +#else + inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); +#endif + } + else { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (jump->flags & IS_BL) + buf_ptr--; + if (*buf_ptr & (1 << 23)) + buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; + else + buf_ptr += 1; + *buf_ptr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; +#else + inline_set_jump_addr((sljit_uw)buf_ptr, (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target, 0); +#endif + } + jump = jump->next; + } + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + const_ = compiler->consts; + while (const_) { + buf_ptr = (sljit_uw*)const_->addr; + const_->addr = (sljit_uw)code_ptr; + + code_ptr[0] = (sljit_uw)buf_ptr; + code_ptr[1] = *buf_ptr; + if (*buf_ptr & (1 << 23)) + buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2; + else + buf_ptr += 1; + /* Set the value again (can be a simple constant). */ + inline_set_const((sljit_uw)code_ptr, *buf_ptr, 0); + code_ptr += 2; + + const_ = const_->next; + } +#endif + + SLJIT_ASSERT(code_ptr - code <= (int)size); + + SLJIT_CACHE_FLUSH(code, code_ptr); + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_size = size * sizeof(sljit_uw); + return code; +} + +/* emit_op inp_flags. + WRITE_BACK must be the first, since it is a flag. */ +#define WRITE_BACK 0x01 +#define ALLOW_IMM 0x02 +#define ALLOW_INV_IMM 0x04 +#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM) +#define ARG_TEST 0x08 + +/* Creates an index in data_transfer_insts array. */ +#define WORD_DATA 0x00 +#define BYTE_DATA 0x10 +#define HALF_DATA 0x20 +#define SIGNED_DATA 0x40 +#define LOAD_DATA 0x80 + +#define EMIT_INSTRUCTION(inst) \ + FAIL_IF(push_inst(compiler, (inst))) + +/* Condition: AL. */ +#define EMIT_DATA_PROCESS_INS(opcode, set_flags, dst, src1, src2) \ + (0xe0000000 | ((opcode) << 21) | (set_flags) | RD(dst) | RN(src1) | (src2)) + +static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size; + sljit_uw push; + + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + /* Push saved registers, temporary registers + stmdb sp!, {..., lr} */ + push = PUSH | (1 << 14); + if (temporaries >= 5) + push |= 1 << 11; + if (temporaries >= 4) + push |= 1 << 10; + if (saveds >= 5) + push |= 1 << 8; + if (saveds >= 4) + push |= 1 << 7; + if (saveds >= 3) + push |= 1 << 6; + if (saveds >= 2) + push |= 1 << 5; + if (saveds >= 1) + push |= 1 << 4; + EMIT_INSTRUCTION(push); + + /* Stack must be aligned to 8 bytes: */ + size = (1 + saveds) * sizeof(sljit_uw); + if (temporaries >= 4) + size += (temporaries - 3) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; + if (local_size > 0) + FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size)); + + if (args >= 1) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG1))); + if (args >= 2) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG2, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2))); + if (args >= 3) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, SLJIT_SAVED_REG3, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG3))); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size; + + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + size = (1 + saveds) * sizeof(sljit_uw); + if (temporaries >= 4) + size += (temporaries - 3) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + sljit_uw pop; + + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + if (compiler->local_size > 0) + FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size)); + + pop = POP | (1 << 15); + /* Push saved registers, temporary registers + ldmia sp!, {..., pc} */ + if (compiler->temporaries >= 5) + pop |= 1 << 11; + if (compiler->temporaries >= 4) + pop |= 1 << 10; + if (compiler->saveds >= 5) + pop |= 1 << 8; + if (compiler->saveds >= 4) + pop |= 1 << 7; + if (compiler->saveds >= 3) + pop |= 1 << 6; + if (compiler->saveds >= 2) + pop |= 1 << 5; + if (compiler->saveds >= 1) + pop |= 1 << 4; + + return push_inst(compiler, pop); +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +/* s/l - store/load (1 bit) + u/s - signed/unsigned (1 bit) + w/b/h/N - word/byte/half/NOT allowed (2 bit) + It contans 16 items, but not all are different. */ + +static sljit_w data_transfer_insts[16] = { +/* s u w */ 0xe5000000 /* str */, +/* s u b */ 0xe5400000 /* strb */, +/* s u h */ 0xe10000b0 /* strh */, +/* s u N */ 0x00000000 /* not allowed */, +/* s s w */ 0xe5000000 /* str */, +/* s s b */ 0xe5400000 /* strb */, +/* s s h */ 0xe10000b0 /* strh */, +/* s s N */ 0x00000000 /* not allowed */, + +/* l u w */ 0xe5100000 /* ldr */, +/* l u b */ 0xe5500000 /* ldrb */, +/* l u h */ 0xe11000b0 /* ldrh */, +/* l u N */ 0x00000000 /* not allowed */, +/* l s w */ 0xe5100000 /* ldr */, +/* l s b */ 0xe11000d0 /* ldrsb */, +/* l s h */ 0xe11000f0 /* ldrsh */, +/* l s N */ 0x00000000 /* not allowed */, +}; + +#define EMIT_DATA_TRANSFER(type, add, wb, target, base1, base2) \ + (data_transfer_insts[(type) >> 4] | ((add) << 23) | ((wb) << 21) | (reg_map[target] << 12) | (reg_map[base1] << 16) | (base2)) +/* Normal ldr/str instruction. + Type2: ldrsb, ldrh, ldrsh */ +#define IS_TYPE1_TRANSFER(type) \ + (data_transfer_insts[(type) >> 4] & 0x04000000) +#define TYPE2_TRANSFER_IMM(imm) \ + (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22)) + +/* flags: */ + /* Arguments are swapped. */ +#define ARGS_SWAPPED 0x01 + /* Inverted immediate. */ +#define INV_IMM 0x02 + /* Source and destination is register. */ +#define REG_DEST 0x04 +#define REG_SOURCE 0x08 + /* One instruction is enough. */ +#define FAST_DEST 0x10 + /* Multiple instructions are required. */ +#define SLOW_DEST 0x20 +/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */ +#define SET_FLAGS (1 << 20) +/* dst: reg + src1: reg + src2: reg or imm (if allowed) + SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */ +#define SRC2_IMM (1 << 25) + +#define EMIT_DATA_PROCESS_INS_AND_RETURN(opcode) \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, (src2 & SRC2_IMM) ? src2 : RM(src2))) + +#define EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(opcode, dst, src1, src2) \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(opcode, flags & SET_FLAGS, dst, src1, src2)) + +#define EMIT_SHIFT_INS_AND_RETURN(opcode) \ + SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \ + if (compiler->shift_imm != 0x20) { \ + SLJIT_ASSERT(src1 == TMP_REG1); \ + SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); \ + if (compiler->shift_imm != 0) \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (compiler->shift_imm << 7) | (opcode << 5) | reg_map[src2])); \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, reg_map[src2])); \ + } \ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, flags & SET_FLAGS, dst, SLJIT_UNUSED, (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | ((flags & ARGS_SWAPPED) ? reg_map[src2] : reg_map[src1]))); + +static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags, + int dst, int src1, int src2) +{ + sljit_w mul_inst; + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + SLJIT_ASSERT(!(flags & INV_IMM)); + EMIT_DATA_PROCESS_INS_AND_RETURN(ADD_DP); + + case SLJIT_ADDC: + SLJIT_ASSERT(!(flags & INV_IMM)); + EMIT_DATA_PROCESS_INS_AND_RETURN(ADC_DP); + + case SLJIT_SUB: + SLJIT_ASSERT(!(flags & INV_IMM)); + if (!(flags & ARGS_SWAPPED)) + EMIT_DATA_PROCESS_INS_AND_RETURN(SUB_DP); + EMIT_DATA_PROCESS_INS_AND_RETURN(RSB_DP); + + case SLJIT_SUBC: + SLJIT_ASSERT(!(flags & INV_IMM)); + if (!(flags & ARGS_SWAPPED)) + EMIT_DATA_PROCESS_INS_AND_RETURN(SBC_DP); + EMIT_DATA_PROCESS_INS_AND_RETURN(RSC_DP); + + case SLJIT_MUL: + SLJIT_ASSERT(!(flags & INV_IMM)); + SLJIT_ASSERT(!(src2 & SRC2_IMM)); + if (SLJIT_UNLIKELY(op & SLJIT_SET_O)) + mul_inst = SMULL | (reg_map[TMP_REG3] << 16) | (reg_map[dst] << 12); + else + mul_inst = MUL | (reg_map[dst] << 16); + + if (dst != src2) + FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src1] << 8) | reg_map[src2])); + else if (dst != src1) + FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[src1])); + else { + /* Rm and Rd must not be the same register. */ + SLJIT_ASSERT(dst != TMP_REG1); + FAIL_IF(push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, reg_map[src2]))); + FAIL_IF(push_inst(compiler, mul_inst | (reg_map[src2] << 8) | reg_map[TMP_REG1])); + } + + if (!(op & SLJIT_SET_O)) + return SLJIT_SUCCESS; + + /* We need to use TMP_REG3. */ + compiler->cache_arg = 0; + compiler->cache_argw = 0; + /* cmp TMP_REG2, dst asr #31. */ + return push_inst(compiler, EMIT_DATA_PROCESS_INS(CMP_DP, SET_FLAGS, SLJIT_UNUSED, TMP_REG3, RM(dst) | 0xfc0)); + + case SLJIT_AND: + if (!(flags & INV_IMM)) + EMIT_DATA_PROCESS_INS_AND_RETURN(AND_DP); + EMIT_DATA_PROCESS_INS_AND_RETURN(BIC_DP); + + case SLJIT_OR: + SLJIT_ASSERT(!(flags & INV_IMM)); + EMIT_DATA_PROCESS_INS_AND_RETURN(ORR_DP); + + case SLJIT_XOR: + SLJIT_ASSERT(!(flags & INV_IMM)); + EMIT_DATA_PROCESS_INS_AND_RETURN(EOR_DP); + + case SLJIT_SHL: + EMIT_SHIFT_INS_AND_RETURN(0); + + case SLJIT_LSHR: + EMIT_SHIFT_INS_AND_RETURN(1); + + case SLJIT_ASHR: + EMIT_SHIFT_INS_AND_RETURN(2); + + case SLJIT_MOV: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); + if (dst != src2) { + if (src2 & SRC2_IMM) { + if (flags & INV_IMM) + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + } + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, reg_map[src2]); + } + return SLJIT_SUCCESS; + + case SLJIT_MOV_UB: + case SLJIT_MOV_SB: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); + if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (op == SLJIT_MOV_UB) + return push_inst(compiler, EMIT_DATA_PROCESS_INS(AND_DP, 0, dst, src2, SRC2_IMM | 0xff)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | reg_map[src2])); + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (24 << 7) | (op == SLJIT_MOV_UB ? 0x20 : 0x40) | reg_map[dst])); +#else + return push_inst(compiler, (op == SLJIT_MOV_UB ? UXTB : SXTB) | RD(dst) | RM(src2)); +#endif + } + else if (dst != src2) { + SLJIT_ASSERT(src2 & SRC2_IMM); + if (flags & INV_IMM) + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + } + return SLJIT_SUCCESS; + + case SLJIT_MOV_UH: + case SLJIT_MOV_SH: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED)); + if ((flags & (REG_DEST | REG_SOURCE)) == (REG_DEST | REG_SOURCE)) { +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | reg_map[src2])); + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, (16 << 7) | (op == SLJIT_MOV_UH ? 0x20 : 0x40) | reg_map[dst])); +#else + return push_inst(compiler, (op == SLJIT_MOV_UH ? UXTH : SXTH) | RD(dst) | RM(src2)); +#endif + } + else if (dst != src2) { + SLJIT_ASSERT(src2 & SRC2_IMM); + if (flags & INV_IMM) + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + } + return SLJIT_SUCCESS; + + case SLJIT_NOT: + if (src2 & SRC2_IMM) { + if (flags & INV_IMM) + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MOV_DP, dst, SLJIT_UNUSED, src2); + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, src2); + } + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(MVN_DP, dst, SLJIT_UNUSED, RM(src2)); + + case SLJIT_CLZ: + SLJIT_ASSERT(!(flags & INV_IMM)); + SLJIT_ASSERT(!(src2 & SRC2_IMM)); + FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2))); + if (flags & SET_FLAGS) + EMIT_FULL_DATA_PROCESS_INS_AND_RETURN(CMP_DP, SLJIT_UNUSED, dst, SRC2_IMM); + return SLJIT_SUCCESS; + } + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; +} + +#undef EMIT_DATA_PROCESS_INS_AND_RETURN +#undef EMIT_FULL_DATA_PROCESS_INS_AND_RETURN +#undef EMIT_SHIFT_INS_AND_RETURN + +/* Tests whether the immediate can be stored in the 12 bit imm field. + Returns with 0 if not possible. */ +static sljit_uw get_immediate(sljit_uw imm) +{ + int rol; + + if (imm <= 0xff) + return SRC2_IMM | imm; + + if (!(imm & 0xff000000)) { + imm <<= 8; + rol = 8; + } + else { + imm = (imm << 24) | (imm >> 8); + rol = 0; + } + + if (!(imm & 0xff000000)) { + imm <<= 8; + rol += 4; + } + + if (!(imm & 0xf0000000)) { + imm <<= 4; + rol += 2; + } + + if (!(imm & 0xc0000000)) { + imm <<= 2; + rol += 1; + } + + if (!(imm & 0x00ffffff)) + return SRC2_IMM | (imm >> 24) | (rol << 8); + else + return 0; +} + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) +static int generate_int(struct sljit_compiler *compiler, int reg, sljit_uw imm, int positive) +{ + sljit_uw mask; + sljit_uw imm1; + sljit_uw imm2; + int rol; + + /* Step1: Search a zero byte (8 continous zero bit). */ + mask = 0xff000000; + rol = 8; + while(1) { + if (!(imm & mask)) { + /* Rol imm by rol. */ + imm = (imm << rol) | (imm >> (32 - rol)); + /* Calculate arm rol. */ + rol = 4 + (rol >> 1); + break; + } + rol += 2; + mask >>= 2; + if (mask & 0x3) { + /* rol by 8. */ + imm = (imm << 8) | (imm >> 24); + mask = 0xff00; + rol = 24; + while (1) { + if (!(imm & mask)) { + /* Rol imm by rol. */ + imm = (imm << rol) | (imm >> (32 - rol)); + /* Calculate arm rol. */ + rol = (rol >> 1) - 8; + break; + } + rol += 2; + mask >>= 2; + if (mask & 0x3) + return 0; + } + break; + } + } + + /* The low 8 bit must be zero. */ + SLJIT_ASSERT(!(imm & 0xff)); + + if (!(imm & 0xff000000)) { + imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8); + imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8); + } + else if (imm & 0xc0000000) { + imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); + imm <<= 8; + rol += 4; + + if (!(imm & 0xff000000)) { + imm <<= 8; + rol += 4; + } + + if (!(imm & 0xf0000000)) { + imm <<= 4; + rol += 2; + } + + if (!(imm & 0xc0000000)) { + imm <<= 2; + rol += 1; + } + + if (!(imm & 0x00ffffff)) + imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + else + return 0; + } + else { + if (!(imm & 0xf0000000)) { + imm <<= 4; + rol += 2; + } + + if (!(imm & 0xc0000000)) { + imm <<= 2; + rol += 1; + } + + imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8); + imm <<= 8; + rol += 4; + + if (!(imm & 0xf0000000)) { + imm <<= 4; + rol += 2; + } + + if (!(imm & 0xc0000000)) { + imm <<= 2; + rol += 1; + } + + if (!(imm & 0x00ffffff)) + imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8); + else + return 0; + } + + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? MOV_DP : MVN_DP, 0, reg, SLJIT_UNUSED, imm1)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(positive ? ORR_DP : BIC_DP, 0, reg, reg, imm2)); + return 1; +} +#endif + +static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_uw imm) +{ + sljit_uw tmp; + +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + if (!(imm & ~0xffff)) + return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)); +#endif + + /* Create imm by 1 inst. */ + tmp = get_immediate(imm); + if (tmp) { + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, tmp)); + return SLJIT_SUCCESS; + } + + tmp = get_immediate(~imm); + if (tmp) { + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, tmp)); + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + /* Create imm by 2 inst. */ + FAIL_IF(generate_int(compiler, reg, imm, 1)); + FAIL_IF(generate_int(compiler, reg, ~imm, 0)); + + /* Load integer. */ + return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), imm); +#else + return emit_imm(compiler, reg, imm); +#endif +} + +/* Can perform an operation using at most 1 instruction. */ +static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw) +{ + sljit_uw imm; + + if (arg & SLJIT_IMM) { + imm = get_immediate(argw); + if (imm) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, imm)); + return -1; + } + imm = get_immediate(~argw); + if (imm) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MVN_DP, 0, reg, SLJIT_UNUSED, imm)); + return -1; + } + return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0; + } + + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* Fast loads/stores. */ + if (arg & 0xf) { + if (!(arg & 0xf0)) { + if (IS_TYPE1_TRANSFER(inp_flags)) { + if (argw >= 0 && argw <= 0xfff) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, argw)); + return -1; + } + if (argw < 0 && argw >= -0xfff) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, -argw)); + return -1; + } + } + else { + if (argw >= 0 && argw <= 0xff) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw))); + return -1; + } + if (argw < 0 && argw >= -0xff) { + if (inp_flags & ARG_TEST) + return 1; + argw = -argw; + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 0, inp_flags & WRITE_BACK, reg, arg & 0xf, TYPE2_TRANSFER_IMM(argw))); + return -1; + } + } + } + else if ((argw & 0x3) == 0 || IS_TYPE1_TRANSFER(inp_flags)) { + if (inp_flags & ARG_TEST) + return 1; + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, + RM((arg >> 4) & 0xf) | (IS_TYPE1_TRANSFER(inp_flags) ? SRC2_IMM : 0) | ((argw & 0x3) << 7))); + return -1; + } + } + + return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0; +} + +/* See getput_arg below. + Note: can_cache is called only for binary operators. Those + operators always uses word arguments without write back. */ +static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + /* Immediate caching is not supported as it would be an operation on constant arguments. */ + if (arg & SLJIT_IMM) + return 0; + + /* Always a simple operation. */ + if (arg & 0xf0) + return 0; + + if (!(arg & 0xf)) { + /* Immediate access. */ + if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff)) + return 1; + return 0; + } + + if (argw <= 0xfffff && argw >= -0xfffff) + return 0; + + if (argw == next_argw && (next_arg & SLJIT_MEM)) + return 1; + + if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= 0xfff || (sljit_uw)next_argw - (sljit_uw)argw <= 0xfff)) + return 1; + + return 0; +} + +#define GETPUT_ARG_DATA_TRANSFER(add, wb, target, base, imm) \ + if (max_delta & 0xf00) \ + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, imm))); \ + else \ + FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(inp_flags, add, wb, target, base, TYPE2_TRANSFER_IMM(imm)))); + +#define TEST_WRITE_BACK() \ + if (inp_flags & WRITE_BACK) { \ + tmp_r = arg & 0xf; \ + if (reg == tmp_r) { \ + /* This can only happen for stores */ \ + /* since ldr reg, [reg, ...]! has no meaning */ \ + SLJIT_ASSERT(!(inp_flags & LOAD_DATA)); \ + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(reg))); \ + reg = TMP_REG3; \ + } \ + } + +/* Emit the necessary instructions. See can_cache above. */ +static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + int tmp_r; + sljit_w max_delta; + sljit_w sign; + + if (arg & SLJIT_IMM) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + return load_immediate(compiler, reg, argw); + } + + SLJIT_ASSERT(arg & SLJIT_MEM); + + tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3; + max_delta = IS_TYPE1_TRANSFER(inp_flags) ? 0xfff : 0xff; + + if ((arg & 0xf) == SLJIT_UNUSED) { + /* Write back is not used. */ + if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta)) { + if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) { + sign = 1; + argw = argw - compiler->cache_argw; + } + else { + sign = 0; + argw = compiler->cache_argw - argw; + } + + if (max_delta & 0xf00) { + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, argw)); + } + else { + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, sign, 0, reg, TMP_REG3, TYPE2_TRANSFER_IMM(argw))); + } + return SLJIT_SUCCESS; + } + + /* With write back, we can create some sophisticated loads, but + it is hard to decide whether we should convert downward (0s) or upward (1s). */ + if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + + compiler->cache_arg = SLJIT_IMM; + compiler->cache_argw = argw; + tmp_r = TMP_REG3; + } + + FAIL_IF(load_immediate(compiler, tmp_r, argw)); + GETPUT_ARG_DATA_TRANSFER(1, 0, reg, tmp_r, 0); + return SLJIT_SUCCESS; + } + + /* Extended imm addressing for [reg+imm] format. */ + sign = (max_delta << 8) | 0xff; + if (!(arg & 0xf0) && argw <= sign && argw >= -sign) { + TEST_WRITE_BACK(); + if (argw >= 0) { + sign = 1; + } + else { + sign = 0; + argw = -argw; + } + + /* Optimization: add is 0x4, sub is 0x2. Sign is 1 for add and 0 for sub. */ + if (max_delta & 0xf00) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 12) | 0xa00)); + else + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP << sign, 0, tmp_r, arg & 0xf, SRC2_IMM | (argw >> 8) | 0xc00)); + + argw &= max_delta; + GETPUT_ARG_DATA_TRANSFER(sign, inp_flags & WRITE_BACK, reg, tmp_r, argw); + return SLJIT_SUCCESS; + } + + if (arg & 0xf0) { + SLJIT_ASSERT((argw & 0x3) && !(max_delta & 0xf00)); + if (inp_flags & WRITE_BACK) + tmp_r = arg & 0xf; + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, tmp_r, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7))); + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, 0, reg, tmp_r, TYPE2_TRANSFER_IMM(0))); + return SLJIT_SUCCESS; + } + + if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= (sljit_uw)max_delta) { + SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); + argw = argw - compiler->cache_argw; + GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, argw); + return SLJIT_SUCCESS; + } + + if (compiler->cache_arg == arg && ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= (sljit_uw)max_delta) { + SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); + argw = compiler->cache_argw - argw; + GETPUT_ARG_DATA_TRANSFER(0, 0, reg, TMP_REG3, argw); + return SLJIT_SUCCESS; + } + + if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) { + TEST_WRITE_BACK(); + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); + return SLJIT_SUCCESS; + } + + if (argw == next_argw && (next_arg & SLJIT_MEM)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + + compiler->cache_arg = SLJIT_IMM; + compiler->cache_argw = argw; + + TEST_WRITE_BACK(); + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, RM(TMP_REG3) | (max_delta & 0xf00 ? SRC2_IMM : 0))); + return SLJIT_SUCCESS; + } + + if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= (sljit_uw)max_delta || (sljit_uw)next_argw - (sljit_uw)argw <= (sljit_uw)max_delta)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, TMP_REG3, reg_map[arg & 0xf])); + + compiler->cache_arg = arg; + compiler->cache_argw = argw; + + GETPUT_ARG_DATA_TRANSFER(1, 0, reg, TMP_REG3, 0); + return SLJIT_SUCCESS; + } + + if ((arg & 0xf) == tmp_r) { + compiler->cache_arg = SLJIT_IMM; + compiler->cache_argw = argw; + tmp_r = TMP_REG3; + } + + FAIL_IF(load_immediate(compiler, tmp_r, argw)); + EMIT_INSTRUCTION(EMIT_DATA_TRANSFER(inp_flags, 1, inp_flags & WRITE_BACK, reg, arg & 0xf, reg_map[tmp_r] | (max_delta & 0xf00 ? SRC2_IMM : 0))); + return SLJIT_SUCCESS; +} + +static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* arg1 goes to TMP_REG1 or src reg + arg2 goes to TMP_REG2, imm or src reg + TMP_REG3 can be used for caching + result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + + /* We prefers register and simple consts. */ + int dst_r; + int src1_r; + int src2_r = 0; + int sugg_src2_r = TMP_REG2; + int flags = GET_FLAGS(op) ? SET_FLAGS : 0; + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + /* Destination check. */ + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) { + dst_r = dst; + flags |= REG_DEST; + if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) + sugg_src2_r = dst_r; + } + else if (dst == SLJIT_UNUSED) { + if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM)) + return SLJIT_SUCCESS; + dst_r = TMP_REG2; + } + else { + SLJIT_ASSERT(dst & SLJIT_MEM); + if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) { + flags |= FAST_DEST; + dst_r = TMP_REG2; + } + else { + flags |= SLOW_DEST; + dst_r = 0; + } + } + + /* Source 1. */ + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3) + src1_r = src1; + else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) { + flags |= ARGS_SWAPPED; + src1_r = src2; + src2 = src1; + src2w = src1w; + } + else { + if ((inp_flags & ALLOW_ANY_IMM) && (src1 & SLJIT_IMM)) { + /* The second check will generate a hit. */ + src2_r = get_immediate(src1w); + if (src2_r) { + flags |= ARGS_SWAPPED; + src1 = src2; + src1w = src2w; + } + if (inp_flags & ALLOW_INV_IMM) { + src2_r = get_immediate(~src1w); + if (src2_r) { + flags |= ARGS_SWAPPED | INV_IMM; + src1 = src2; + src1w = src2w; + } + } + } + + src1_r = 0; + if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) { + FAIL_IF(compiler->error); + src1_r = TMP_REG1; + } + } + + /* Source 2. */ + if (src2_r == 0) { + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) { + src2_r = src2; + flags |= REG_SOURCE; + if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) + dst_r = src2_r; + } + else do { /* do { } while(0) is used because of breaks. */ + if ((inp_flags & ALLOW_ANY_IMM) && (src2 & SLJIT_IMM)) { + src2_r = get_immediate(src2w); + if (src2_r) + break; + if (inp_flags & ALLOW_INV_IMM) { + src2_r = get_immediate(~src2w); + if (src2_r) { + flags |= INV_IMM; + break; + } + } + } + + /* src2_r is 0. */ + if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) { + FAIL_IF(compiler->error); + src2_r = sugg_src2_r; + } + } while (0); + } + + /* src1_r, src2_r and dst_r can be zero (=unprocessed) or non-zero. + If they are zero, they must not be registers. */ + if (src1_r == 0 && src2_r == 0 && dst_r == 0) { + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + SLJIT_ASSERT(!(flags & ARGS_SWAPPED)); + flags |= ARGS_SWAPPED; + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); + } + src1_r = TMP_REG1; + src2_r = TMP_REG2; + } + else if (src1_r == 0 && src2_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + src1_r = TMP_REG1; + } + else if (src1_r == 0 && dst_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + src1_r = TMP_REG1; + } + else if (src2_r == 0 && dst_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); + src2_r = sugg_src2_r; + } + + if (dst_r == 0) + dst_r = TMP_REG2; + + if (src1_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0)); + src1_r = TMP_REG1; + } + + if (src2_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0)); + src2_r = sugg_src2_r; + } + + FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + + if (flags & (FAST_DEST | SLOW_DEST)) { + if (flags & FAST_DEST) + FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw)); + else + FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0)); + } + return SLJIT_SUCCESS; +} + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__GNUC__) +extern unsigned int __aeabi_uidivmod(unsigned numerator, unsigned denominator); +extern unsigned int __aeabi_idivmod(unsigned numerator, unsigned denominator); +#else +#error "Software divmod functions are needed" +#endif + +#ifdef __cplusplus +} +#endif + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + CHECK_ERROR(); + check_sljit_emit_op0(compiler, op); + + op = GET_OPCODE(op); + switch (op) { + case SLJIT_BREAKPOINT: + EMIT_INSTRUCTION(BKPT); + break; + case SLJIT_NOP: + EMIT_INSTRUCTION(NOP); + break; + case SLJIT_UMUL: + case SLJIT_SMUL: +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) + | (reg_map[SLJIT_TEMPORARY_REG2] << 16) + | (reg_map[SLJIT_TEMPORARY_REG1] << 12) + | (reg_map[SLJIT_TEMPORARY_REG1] << 8) + | reg_map[SLJIT_TEMPORARY_REG2]); +#else + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, RM(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, (op == SLJIT_UMUL ? UMULL : SMULL) + | (reg_map[SLJIT_TEMPORARY_REG2] << 16) + | (reg_map[SLJIT_TEMPORARY_REG1] << 12) + | (reg_map[SLJIT_TEMPORARY_REG1] << 8) + | reg_map[TMP_REG1]); +#endif + case SLJIT_UDIV: + case SLJIT_SDIV: + if (compiler->temporaries >= 3) + EMIT_INSTRUCTION(0xe52d2008 /* str r2, [sp, #-8]! */); +#if defined(__GNUC__) + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, + (op == SLJIT_UDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); +#else +#error "Software divmod functions are needed" +#endif + if (compiler->temporaries >= 3) + return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_UB: + return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOV_SB: + return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOV_UH: + return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOV_SH: + return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_MOVU: + case SLJIT_MOVU_UI: + case SLJIT_MOVU_SI: + return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_UB: + return emit_op(compiler, SLJIT_MOV_UB, ALLOW_ANY_IMM | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOVU_SB: + return emit_op(compiler, SLJIT_MOV_SB, ALLOW_ANY_IMM | SIGNED_DATA | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOVU_UH: + return emit_op(compiler, SLJIT_MOV_UH, ALLOW_ANY_IMM | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOVU_SH: + return emit_op(compiler, SLJIT_MOV_SH, ALLOW_ANY_IMM | SIGNED_DATA | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_NOT: + return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_NEG: +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, SLJIT_SUB | GET_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw); + + case SLJIT_CLZ: + return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + CHECK_ERROR(); + check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + case SLJIT_ADDC: + case SLJIT_SUB: + case SLJIT_SUBC: + case SLJIT_OR: + case SLJIT_XOR: + return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_MUL: + return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_AND: + return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SHL: + case SLJIT_LSHR: + case SLJIT_ASHR: + if (src2 & SLJIT_IMM) { + compiler->shift_imm = src2w & 0x1f; + return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w); + } + else { + compiler->shift_imm = 0x20; + return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w); + } + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + check_sljit_get_register_index(reg); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + CHECK_ERROR(); + check_sljit_emit_op_custom(compiler, instruction, size); + SLJIT_ASSERT(size == 4); + + return push_inst(compiler, *(sljit_uw*)instruction); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + +/* 0 - no fpu + 1 - vfp */ +static int arm_fpu_type = -1; + +static void init_compiler() +{ + if (arm_fpu_type != -1) + return; + + /* TODO: Only the OS can help to determine the correct fpu type. */ + arm_fpu_type = 1; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + if (arm_fpu_type == -1) + init_compiler(); + return arm_fpu_type; +} + +#else + +#define arm_fpu_type 1 + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + /* Always available. */ + return 1; +} + +#endif + +#define EMIT_FPU_DATA_TRANSFER(add, load, base, freg, offs) \ + (VSTR | ((add) << 23) | ((load) << 20) | (reg_map[base] << 16) | (freg << 12) | (offs)) +#define EMIT_FPU_OPERATION(opcode, dst, src1, src2) \ + ((opcode) | ((dst) << 12) | (src1) | ((src2) << 16)) + +static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw) +{ + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* Fast loads and stores. */ + if ((arg & 0xf) && !(arg & 0xf0) && (argw & 0x3) == 0) { + if (argw >= 0 && argw <= 0x3ff) { + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, arg & 0xf, fpu_reg, argw >> 2)); + return SLJIT_SUCCESS; + } + if (argw < 0 && argw >= -0x3ff) { + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, arg & 0xf, fpu_reg, (-argw) >> 2)); + return SLJIT_SUCCESS; + } + if (argw >= 0 && argw <= 0x3ffff) { + SLJIT_ASSERT(get_immediate(argw & 0x3fc00)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00))); + argw &= 0x3ff; + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, argw >> 2)); + return SLJIT_SUCCESS; + } + if (argw < 0 && argw >= -0x3ffff) { + argw = -argw; + SLJIT_ASSERT(get_immediate(argw & 0x3fc00)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(SUB_DP, 0, TMP_REG1, arg & 0xf, get_immediate(argw & 0x3fc00))); + argw &= 0x3ff; + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG1, fpu_reg, argw >> 2)); + return SLJIT_SUCCESS; + } + } + + if (arg & 0xf0) { + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG1, arg & 0xf, RM((arg >> 4) & 0xf) | ((argw & 0x3) << 7))); + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG1, fpu_reg, 0)); + return SLJIT_SUCCESS; + } + + if (compiler->cache_arg == arg && ((argw - compiler->cache_argw) & 0x3) == 0) { + if (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= 0x3ff) { + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, (argw - compiler->cache_argw) >> 2)); + return SLJIT_SUCCESS; + } + if (((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= 0x3ff) { + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(0, load, TMP_REG3, fpu_reg, (compiler->cache_argw - argw) >> 2)); + return SLJIT_SUCCESS; + } + } + + compiler->cache_arg = arg; + compiler->cache_argw = argw; + if (arg & 0xf) { + FAIL_IF(load_immediate(compiler, TMP_REG1, argw)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(ADD_DP, 0, TMP_REG3, arg & 0xf, reg_map[TMP_REG1])); + } + else + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + + EMIT_INSTRUCTION(EMIT_FPU_DATA_TRANSFER(1, load, TMP_REG3, fpu_reg, 0)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int dst_freg; + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (GET_OPCODE(op) == SLJIT_FCMP) { + if (dst > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw)); + dst = TMP_FREG1; + } + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw)); + src = TMP_FREG2; + } + EMIT_INSTRUCTION(VCMP_F64 | (dst << 12) | src); + EMIT_INSTRUCTION(VMRS); + return SLJIT_SUCCESS; + } + + dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, dst_freg, 1, src, srcw)); + src = dst_freg; + } + + switch (op) { + case SLJIT_FMOV: + if (src != dst_freg && dst_freg != TMP_FREG1) + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMOV_F64, dst_freg, src, 0)); + break; + case SLJIT_FNEG: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VNEG_F64, dst_freg, src, 0)); + break; + case SLJIT_FABS: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VABS_F64, dst_freg, src, 0)); + break; + } + + if (dst_freg == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_freg; + + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_freg = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src2 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); + src2 = TMP_FREG2; + } + + if (src1 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); + src1 = TMP_FREG1; + } + + switch (op) { + case SLJIT_FADD: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VADD_F64, dst_freg, src2, src1)); + break; + + case SLJIT_FSUB: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VSUB_F64, dst_freg, src2, src1)); + break; + + case SLJIT_FMUL: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VMUL_F64, dst_freg, src2, src1)); + break; + + case SLJIT_FDIV: + EMIT_INSTRUCTION(EMIT_FPU_OPERATION(VDIV_F64, dst_freg, src2, src1)); + break; + } + + if (dst_freg == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + int size; + + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + size = (1 + saveds) * sizeof(sljit_uw); + if (temporaries >= 4) + size += (temporaries - 3) * sizeof(sljit_uw); + local_size += size; + local_size = (local_size + 7) & ~7; + local_size -= size; + compiler->local_size = local_size; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, 0, dst, SLJIT_UNUSED, RM(TMP_REG3))); + else if (dst & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_DATA, TMP_REG3, dst, dstw)) + return compiler->error; + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG2, SLJIT_UNUSED, RM(TMP_REG3))); + compiler->cache_arg = 0; + compiler->cache_argw = 0; + return getput_arg(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(src))); + else if (src & SLJIT_MEM) { + if (getput_arg_fast(compiler, WORD_DATA | LOAD_DATA, TMP_REG3, src, srcw)) + FAIL_IF(compiler->error); + else { + compiler->cache_arg = 0; + compiler->cache_argw = 0; + FAIL_IF(getput_arg(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, 0, 0)); + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG3, SLJIT_UNUSED, RM(TMP_REG2))); + } + } + else if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, TMP_REG3, srcw)); + return push_inst(compiler, BLX | RM(TMP_REG3)); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +static sljit_uw get_cc(int type) +{ + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_C_FLOAT_EQUAL: + return 0x00000000; + + case SLJIT_C_NOT_EQUAL: + case SLJIT_C_MUL_OVERFLOW: + case SLJIT_C_FLOAT_NOT_EQUAL: + return 0x10000000; + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + return 0x30000000; + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + return 0x20000000; + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + return 0x80000000; + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + return 0x90000000; + + case SLJIT_C_SIG_LESS: + return 0xb0000000; + + case SLJIT_C_SIG_GREATER_EQUAL: + return 0xa0000000; + + case SLJIT_C_SIG_GREATER: + return 0xc0000000; + + case SLJIT_C_SIG_LESS_EQUAL: + return 0xd0000000; + + case SLJIT_C_OVERFLOW: + case SLJIT_C_FLOAT_NAN: + return 0x60000000; + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_FLOAT_NOT_NAN: + return 0x70000000; + + default: /* SLJIT_JUMP */ + return 0xe0000000; + } +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + check_sljit_emit_label(compiler); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + struct sljit_jump *jump; + + CHECK_ERROR_PTR(); + check_sljit_emit_jump(compiler, type); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + /* In ARM, we don't need to touch the arguments. */ +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (type >= SLJIT_FAST_CALL) + PTR_FAIL_IF(prepare_blx(compiler)); + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, + type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(type), 0)); + + if (jump->flags & SLJIT_REWRITABLE_JUMP) { + jump->addr = compiler->size; + compiler->patches++; + } + + if (type >= SLJIT_FAST_CALL) { + jump->flags |= IS_BL; + PTR_FAIL_IF(emit_blx(compiler)); + } + + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) + jump->addr = compiler->size; +#else + if (type >= SLJIT_FAST_CALL) + jump->flags |= IS_BL; + PTR_FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); + PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(type))); + jump->addr = compiler->size; +#endif + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + struct sljit_jump *jump; + + CHECK_ERROR(); + check_sljit_emit_ijump(compiler, type, src, srcw); + + /* In ARM, we don't need to touch the arguments. */ + if (src & SLJIT_IMM) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0)); + jump->u.target = srcw; + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + if (type >= SLJIT_FAST_CALL) + FAIL_IF(prepare_blx(compiler)); + FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0)); + if (type >= SLJIT_FAST_CALL) + FAIL_IF(emit_blx(compiler)); +#else + FAIL_IF(emit_imm(compiler, TMP_REG1, 0)); + FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1))); +#endif + jump->addr = compiler->size; + } + else { + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src)); + + SLJIT_ASSERT(src & SLJIT_MEM); + FAIL_IF(emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG2)); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + int reg; + sljit_uw cc; + + CHECK_ERROR(); + check_sljit_emit_cond_value(compiler, op, dst, dstw, type); + + if (dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + cc = get_cc(type); + if (GET_OPCODE(op) == SLJIT_OR) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(ORR_DP, 0, dst, dst, SRC2_IMM | 1) & ~COND_MASK) | cc); + if (op & SLJIT_SET_E) + return push_inst(compiler, EMIT_DATA_PROCESS_INS(MOV_DP, SET_FLAGS, TMP_REG1, SLJIT_UNUSED, RM(dst))); + return SLJIT_SUCCESS; + } + + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 0)); + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, TMP_REG1, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return emit_op(compiler, op, ALLOW_IMM, dst, dstw, TMP_REG1, 0, dst, dstw); + } + + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + + EMIT_INSTRUCTION(EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 0)); + EMIT_INSTRUCTION((EMIT_DATA_PROCESS_INS(MOV_DP, 0, reg, SLJIT_UNUSED, SRC2_IMM | 1) & ~COND_MASK) | cc); + + if (reg == TMP_REG2) + return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + struct sljit_const *const_; + int reg; + + CHECK_ERROR_PTR(); + check_sljit_emit_const(compiler, dst, dstw, init_value); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + +#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) + PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_DATA | LOAD_DATA, 1, 0, reg, TMP_PC, 0), init_value)); + compiler->patches++; +#else + PTR_FAIL_IF(emit_imm(compiler, reg, init_value)); +#endif + set_const(const_, compiler); + + if (reg == TMP_REG2 && dst != SLJIT_UNUSED) + if (emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)) + return NULL; + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + inline_set_jump_addr(addr, new_addr, 1); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + inline_set_const(addr, new_constant, 1); +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c new file mode 100644 index 0000000000..c0cc8b58bb --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_32.c @@ -0,0 +1,405 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* mips 32-bit arch dependent functions. */ + +static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm) +{ + if (!(imm & ~0xffff)) + return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); + + if (imm < 0 && imm >= SIMM_MIN) + return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); + + FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar)); + return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; +} + +#define EMIT_LOGICAL(op_imm, op_norm) \ + if (flags & SRC2_IMM) { \ + if (op & SLJIT_SET_E) \ + FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ + if (CHECK_FLAGS(SLJIT_SET_E)) \ + FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ + } \ + else { \ + if (op & SLJIT_SET_E) \ + FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ + if (CHECK_FLAGS(SLJIT_SET_E)) \ + FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ + } + +#define EMIT_SHIFT(op_imm, op_norm) \ + if (flags & SRC2_IMM) { \ + if (op & SLJIT_SET_E) \ + FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ + if (CHECK_FLAGS(SLJIT_SET_E)) \ + FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ + } \ + else { \ + if (op & SLJIT_SET_E) \ + FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ + if (CHECK_FLAGS(SLJIT_SET_E)) \ + FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \ + } + +static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags, + int dst, int src1, sljit_w src2) +{ + int overflow_ra = 0; + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1)); + if (src2 < 0) + FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1)); + } + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); + if (op & SLJIT_SET_C) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + else { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + } + } + /* dst may be the same as src1 or src2. */ + if (CHECK_FLAGS(SLJIT_SET_E)) + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG)); + if (src2 < 0) + FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG)); + } + } + else { + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); + FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1)); + if (src1 != dst) + overflow_ra = DR(src1); + else if (src2 != dst) + overflow_ra = DR(src2); + else { + /* Rare ocasion. */ + FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2)); + overflow_ra = TMP_EREG2; + } + } + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); + /* dst may be the same as src1 or src2. */ + if (CHECK_FLAGS(SLJIT_SET_E)) + FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG)); + } + } + + /* a + b >= a | b (otherwise, the carry should be set to 1). */ + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); + if (op & SLJIT_SET_O) + return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); + return SLJIT_SUCCESS; + + case SLJIT_ADDC: + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_C) { + if (src2 >= 0) + FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1)); + else { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1)); + FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1)); + } + } + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); + } else { + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); + /* dst may be the same as src1 or src2. */ + FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); + } + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1)); + + FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); + if (!(op & SLJIT_SET_C)) + return SLJIT_SUCCESS; + + /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */ + FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2)); + FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2)); + /* Set carry flag. */ + return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG); + + case SLJIT_SUB: + if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || src2 == SIMM_MIN)) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1)); + if (src2 < 0) + FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1)); + if (src1 != dst) + overflow_ra = DR(src1); + else { + /* Rare ocasion. */ + FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2)); + overflow_ra = TMP_EREG2; + } + } + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); + /* dst may be the same as src1 or src2. */ + if (CHECK_FLAGS(SLJIT_SET_E)) + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); + } + else { + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); + FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1)); + if (src1 != dst) + overflow_ra = DR(src1); + else { + /* Rare ocasion. */ + FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2)); + overflow_ra = TMP_EREG2; + } + } + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (op & (SLJIT_SET_U | SLJIT_SET_C)) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); + if (op & SLJIT_SET_U) + FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG)); + if (op & SLJIT_SET_S) { + FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG)); + FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG)); + } + /* dst may be the same as src1 or src2. */ + if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C)) + FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); + } + + if (op & SLJIT_SET_O) { + FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); + FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG)); + return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); + } + return SLJIT_SUCCESS; + + case SLJIT_SUBC: + if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { + FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + if (flags & SRC2_IMM) { + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1)); + /* dst may be the same as src1 or src2. */ + FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); + } + else { + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); + /* dst may be the same as src1 or src2. */ + FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); + } + + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1)); + + FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); + + if (op & SLJIT_SET_C) + FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG)); + + return SLJIT_SUCCESS; + + case SLJIT_MUL: + SLJIT_ASSERT(!(flags & SRC2_IMM)); + if (!(op & SLJIT_SET_O)) { +#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) + return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); +#else + FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); + return push_inst(compiler, MFLO | D(dst), DR(dst)); +#endif + } + FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1)); + FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); + FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2)); + return push_inst(compiler, SUBU | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); + + case SLJIT_AND: + EMIT_LOGICAL(ANDI, AND); + return SLJIT_SUCCESS; + + case SLJIT_OR: + EMIT_LOGICAL(ORI, OR); + return SLJIT_SUCCESS; + + case SLJIT_XOR: + EMIT_LOGICAL(XORI, XOR); + return SLJIT_SUCCESS; + + case SLJIT_SHL: + EMIT_SHIFT(SLL, SLLV); + return SLJIT_SUCCESS; + + case SLJIT_LSHR: + EMIT_SHIFT(SRL, SRLV); + return SLJIT_SUCCESS; + + case SLJIT_ASHR: + EMIT_SHIFT(SRA, SRAV); + return SLJIT_SUCCESS; + + case SLJIT_MOV: + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + SLJIT_ASSERT(src1 == TMP_REG1); + if (dst != src2) + return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UB: + case SLJIT_MOV_SB: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SB) { +#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) + return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); +#else + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); +#endif + } + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); + } + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UH: + case SLJIT_MOV_SH: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SH) { +#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) + return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); +#else + FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); + return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); +#endif + } + return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); + } + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_NOT: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (CHECK_FLAGS(SLJIT_SET_E)) + FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); + return SLJIT_SUCCESS; + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); +#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) + if (op & SLJIT_SET_E) + FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); + if (CHECK_FLAGS(SLJIT_SET_E)) + FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); +#else + if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { + FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); + return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); + } + /* Nearly all instructions are unmovable in the following sequence. */ + FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + /* Check zero. */ + FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS)); + /* Check sign bit. */ + FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS)); + /* Loop for searching the highest bit. */ + FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1))); + FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS)); + if (op & SLJIT_SET_E) + return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); +#endif + return SLJIT_SUCCESS; + } + + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value) +{ + FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg))); + return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 2); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 2); +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c new file mode 100644 index 0000000000..3c6ee663e1 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c @@ -0,0 +1,1829 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ + return "MIPS" SLJIT_CPUINFO; +} + +/* Latest MIPS architecture. */ +/* Detect SLJIT_MIPS_32_64 */ + +/* Length of an instruction word + Both for mips-32 and mips-64 */ +typedef sljit_ui sljit_ins; + +#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) +#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) +#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) +#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 4) + +/* For position independent code, t9 must contain the function address. */ +#define PIC_ADDR_REG TMP_REG2 + +/* TMP_EREG1 is used mainly for literal encoding on 64 bit. */ +#define TMP_EREG1 15 +#define TMP_EREG2 24 +/* Floating point status register. */ +#define FCSR_REG 31 +/* Return address register. */ +#define RETURN_ADDR_REG 31 + +/* Flags are keept in volatile registers. */ +#define EQUAL_FLAG 7 +/* And carry flag as well. */ +#define ULESS_FLAG 10 +#define UGREATER_FLAG 11 +#define LESS_FLAG 12 +#define GREATER_FLAG 13 +#define OVERFLOW_FLAG 14 + +#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) +#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2) + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ + +#define S(s) (reg_map[s] << 21) +#define T(t) (reg_map[t] << 16) +#define D(d) (reg_map[d] << 11) +/* Absolute registers. */ +#define SA(s) ((s) << 21) +#define TA(t) ((t) << 16) +#define DA(d) ((d) << 11) +#define FT(t) ((t) << (16 + 1)) +#define FS(s) ((s) << (11 + 1)) +#define FD(d) ((d) << (6 + 1)) +#define IMM(imm) ((imm) & 0xffff) +#define SH_IMM(imm) ((imm & 0x1f) << 6) + +#define DR(dr) (reg_map[dr]) +#define HI(opcode) ((opcode) << 26) +#define LO(opcode) (opcode) +#define FMT_D (17 << 21) + +#define ABS_D (HI(17) | FMT_D | LO(5)) +#define ADD_D (HI(17) | FMT_D | LO(0)) +#define ADDU (HI(0) | LO(33)) +#define ADDIU (HI(9)) +#define AND (HI(0) | LO(36)) +#define ANDI (HI(12)) +#define B (HI(4)) +#define BAL (HI(1) | (17 << 16)) +#define BC1F (HI(17) | (8 << 21)) +#define BC1T (HI(17) | (8 << 21) | (1 << 16)) +#define BEQ (HI(4)) +#define BGEZ (HI(1) | (1 << 16)) +#define BGTZ (HI(7)) +#define BLEZ (HI(6)) +#define BLTZ (HI(1) | (0 << 16)) +#define BNE (HI(5)) +#define BREAK (HI(0) | LO(13)) +#define C_UN_D (HI(17) | FMT_D | LO(49)) +#define C_UEQ_D (HI(17) | FMT_D | LO(51)) +#define C_ULE_D (HI(17) | FMT_D | LO(55)) +#define C_ULT_D (HI(17) | FMT_D | LO(53)) +#define DIV (HI(0) | LO(26)) +#define DIVU (HI(0) | LO(27)) +#define DIV_D (HI(17) | FMT_D | LO(3)) +#define J (HI(2)) +#define JAL (HI(3)) +#define JALR (HI(0) | LO(9)) +#define JR (HI(0) | LO(8)) +#define LD (HI(55)) +#define LDC1 (HI(53)) +#define LUI (HI(15)) +#define LW (HI(35)) +#define NEG_D (HI(17) | FMT_D | LO(7)) +#define MFHI (HI(0) | LO(16)) +#define MFLO (HI(0) | LO(18)) +#define MOV_D (HI(17) | FMT_D | LO(6)) +#define CFC1 (HI(17) | (2 << 21)) +#define MOVN (HI(0) | LO(11)) +#define MOVZ (HI(0) | LO(10)) +#define MUL_D (HI(17) | FMT_D | LO(2)) +#define MULT (HI(0) | LO(24)) +#define MULTU (HI(0) | LO(25)) +#define NOP (HI(0) | LO(0)) +#define NOR (HI(0) | LO(39)) +#define OR (HI(0) | LO(37)) +#define ORI (HI(13)) +#define SD (HI(63)) +#define SDC1 (HI(61)) +#define SLT (HI(0) | LO(42)) +#define SLTI (HI(10)) +#define SLTIU (HI(11)) +#define SLTU (HI(0) | LO(43)) +#define SLL (HI(0) | LO(0)) +#define SLLV (HI(0) | LO(4)) +#define SRL (HI(0) | LO(2)) +#define SRLV (HI(0) | LO(6)) +#define SRA (HI(0) | LO(3)) +#define SRAV (HI(0) | LO(7)) +#define SUB_D (HI(17) | FMT_D | LO(1)) +#define SUBU (HI(0) | LO(35)) +#define SW (HI(43)) +#define XOR (HI(0) | LO(38)) +#define XORI (HI(14)) + +#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) +#define CLZ (HI(28) | LO(32)) +#define MUL (HI(28) | LO(2)) +#define SEB (HI(31) | (16 << 6) | LO(32)) +#define SEH (HI(31) | (24 << 6) | LO(32)) +#endif + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define ADDU_W ADDU +#define ADDIU_W ADDIU +#define SLL_W SLL +#define SUBU_W SUBU +#else +#define ADDU_W DADDU +#define ADDIU_W DADDIU +#define SLL_W DSLL +#define SUBU_W DSUBU +#endif + +#define SIMM_MAX (0x7fff) +#define SIMM_MIN (-0x8000) +#define UIMM_MAX (0xffff) + +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = { + 0, 2, 5, 6, 3, 8, 17, 18, 19, 20, 21, 16, 4, 25, 9, 29 +}; + +/* dest_reg is the absolute name of the register + Useful for reordering instructions in the delay slot. */ +static int push_inst(struct sljit_compiler *compiler, sljit_ins ins, int delay_slot) +{ + sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + *ptr = ins; + compiler->size++; + compiler->delay_slot = delay_slot; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_ins invert_branch(int flags) +{ + return (flags & IS_BIT26_COND) ? (1 << 26) : (1 << 16); +} + +static SLJIT_INLINE sljit_ins* optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code) +{ + sljit_w diff; + sljit_uw target_addr; + sljit_ins *inst; + sljit_ins saved_inst; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + return code_ptr; + + if (jump->flags & JUMP_ADDR) + target_addr = jump->u.target; + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + target_addr = (sljit_uw)(code + jump->u.label->size); + } + inst = (sljit_ins*)jump->addr; + if (jump->flags & IS_COND) + inst--; + + /* B instructions. */ + if (jump->flags & IS_MOVABLE) { + diff = ((sljit_w)target_addr - (sljit_w)(inst)) >> 2; + if (diff <= SIMM_MAX && diff >= SIMM_MIN) { + jump->flags |= PATCH_B; + + if (!(jump->flags & IS_COND)) { + inst[0] = inst[-1]; + inst[-1] = (jump->flags & IS_JAL) ? BAL : B; + jump->addr -= sizeof(sljit_ins); + return inst; + } + saved_inst = inst[0]; + inst[0] = inst[-1]; + inst[-1] = saved_inst ^ invert_branch(jump->flags); + jump->addr -= 2 * sizeof(sljit_ins); + return inst; + } + } + + diff = ((sljit_w)target_addr - (sljit_w)(inst + 1)) >> 2; + if (diff <= SIMM_MAX && diff >= SIMM_MIN) { + jump->flags |= PATCH_B; + + if (!(jump->flags & IS_COND)) { + inst[0] = (jump->flags & IS_JAL) ? BAL : B; + inst[1] = NOP; + return inst + 1; + } + inst[0] = inst[0] ^ invert_branch(jump->flags); + inst[1] = NOP; + jump->addr -= sizeof(sljit_ins); + return inst + 1; + } + + if (jump->flags & IS_COND) { + if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) { + jump->flags |= PATCH_J; + inst[0] = (inst[0] & 0xffff0000) | 3; + inst[1] = NOP; + inst[2] = J; + inst[3] = NOP; + jump->addr += sizeof(sljit_ins); + return inst + 3; + } + return code_ptr; + } + + /* J instuctions. */ + if (jump->flags & IS_MOVABLE) { + if ((target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) { + jump->flags |= PATCH_J; + inst[0] = inst[-1]; + inst[-1] = (jump->flags & IS_JAL) ? JAL : J; + jump->addr -= sizeof(sljit_ins); + return inst; + } + } + + if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) { + jump->flags |= PATCH_J; + inst[0] = (jump->flags & IS_JAL) ? JAL : J; + inst[1] = NOP; + return inst + 1; + } + + return code_ptr; +} + +#ifdef __GNUC__ +static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr) +{ + SLJIT_CACHE_FLUSH(code, code_ptr); +} +#endif + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_ins *code; + sljit_ins *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; + sljit_uw word_count; + sljit_uw addr; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + + CHECK_ERROR_PTR(); + check_sljit_generate_code(compiler); + reverse_buf(compiler); + + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + word_count = 0; + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + do { + buf_ptr = (sljit_ins*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 2); + do { + *code_ptr = *buf_ptr++; + SLJIT_ASSERT(!label || label->size >= word_count); + SLJIT_ASSERT(!jump || jump->addr >= word_count); + SLJIT_ASSERT(!const_ || const_->addr >= word_count); + /* These structures are ordered by their address. */ + if (label && label->size == word_count) { + /* Just recording the address. */ + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + if (jump && jump->addr == word_count) { +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + jump->addr = (sljit_uw)(code_ptr - 3); +#else + jump->addr = (sljit_uw)(code_ptr - 6); +#endif + code_ptr = optimize_jump(jump, code_ptr, code); + jump = jump->next; + } + if (const_ && const_->addr == word_count) { + /* Just recording the address. */ + const_->addr = (sljit_uw)code_ptr; + const_ = const_->next; + } + code_ptr ++; + word_count ++; + } while (buf_ptr < buf_end); + + buf = buf->next; + } while (buf); + + if (label && label->size == word_count) { + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + SLJIT_ASSERT(code_ptr - code <= (int)compiler->size); + + jump = compiler->jumps; + while (jump) { + do { + addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + buf_ptr = (sljit_ins*)jump->addr; + + if (jump->flags & PATCH_B) { + addr = (sljit_w)(addr - (jump->addr + sizeof(sljit_ins))) >> 2; + SLJIT_ASSERT((sljit_w)addr <= SIMM_MAX && (sljit_w)addr >= SIMM_MIN); + buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff); + break; + } + if (jump->flags & PATCH_J) { + SLJIT_ASSERT((addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)); + buf_ptr[0] |= (addr >> 2) & 0x03ffffff; + break; + } + + /* Set the fields of immediate loads. */ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); + buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); +#else + buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff); + buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff); + buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff); + buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff); +#endif + } while (0); + jump = jump->next; + } + + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_size = compiler->size * sizeof(sljit_ins); +#ifndef __GNUC__ + SLJIT_CACHE_FLUSH(code, code_ptr); +#else + /* GCC workaround for invalid code generation with -O2. */ + sljit_cache_flush(code, code_ptr); +#endif + return code; +} + +/* Creates an index in data_transfer_insts array. */ +#define WORD_DATA 0x00 +#define BYTE_DATA 0x01 +#define HALF_DATA 0x02 +#define INT_DATA 0x03 +#define SIGNED_DATA 0x04 +#define LOAD_DATA 0x08 + +#define MEM_MASK 0x0f + +#define WRITE_BACK 0x00010 +#define ARG_TEST 0x00020 +#define CUMULATIVE_OP 0x00040 +#define LOGICAL_OP 0x00080 +#define IMM_OP 0x00100 +#define SRC2_IMM 0x00200 + +#define UNUSED_DEST 0x00400 +#define REG_DEST 0x00800 +#define REG1_SOURCE 0x01000 +#define REG2_SOURCE 0x02000 +#define SLOW_SRC1 0x04000 +#define SLOW_SRC2 0x08000 +#define SLOW_DEST 0x10000 + +/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. */ +#define CHECK_FLAGS(list) \ + (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list)))) + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#include "sljitNativeMIPS_32.c" +#else +#include "sljitNativeMIPS_64.c" +#endif + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define STACK_STORE SW +#define STACK_LOAD LW +#else +#define STACK_STORE SD +#define STACK_LOAD LD +#endif + +static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + sljit_ins base; + + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + compiler->has_locals = local_size > 0; + local_size += (saveds + 2 + 4) * sizeof(sljit_w); + local_size = (local_size + 15) & ~0xf; + compiler->local_size = local_size; + + if (local_size <= SIMM_MAX) { + /* Frequent case. */ + FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(-local_size), DR(REAL_STACK_PTR))); + base = S(REAL_STACK_PTR); + } + else { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size)); + FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, SUBU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(REAL_STACK_PTR), DR(REAL_STACK_PTR))); + base = S(TMP_REG2); + local_size = 0; + } + + FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (saveds >= 1) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (saveds >= 2) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (saveds >= 3) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (saveds >= 4) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), MOVABLE_INS)); + if (saveds >= 5) + FAIL_IF(push_inst(compiler, STACK_STORE | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), MOVABLE_INS)); + + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(SLJIT_LOCALS_REG) | IMM(4 * sizeof(sljit_w)), DR(SLJIT_LOCALS_REG))); + + if (args >= 1) + FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_SAVED_REG1), DR(SLJIT_SAVED_REG1))); + if (args >= 2) + FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_SAVED_REG2), DR(SLJIT_SAVED_REG2))); + if (args >= 3) + FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_SAVED_REG3), DR(SLJIT_SAVED_REG3))); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + compiler->has_locals = local_size > 0; + local_size += (saveds + 2 + 4) * sizeof(sljit_w); + compiler->local_size = (local_size + 15) & ~0xf; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + int local_size; + sljit_ins base; + + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + local_size = compiler->local_size; + if (local_size <= SIMM_MAX) + base = S(REAL_STACK_PTR); + else { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size)); + FAIL_IF(push_inst(compiler, ADDU_W | S(REAL_STACK_PTR) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1))); + base = S(TMP_REG1); + local_size = 0; + } + + FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - 1 * (int)sizeof(sljit_w)), RETURN_ADDR_REG)); + if (compiler->saveds >= 5) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG2) | IMM(local_size - 7 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG2))); + if (compiler->saveds >= 4) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_EREG1) | IMM(local_size - 6 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_EREG1))); + if (compiler->saveds >= 3) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG3) | IMM(local_size - 5 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG3))); + if (compiler->saveds >= 2) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG2) | IMM(local_size - 4 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG2))); + if (compiler->saveds >= 1) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_SAVED_REG1) | IMM(local_size - 3 * (int)sizeof(sljit_w)), DR(SLJIT_SAVED_REG1))); + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(SLJIT_LOCALS_REG) | IMM(local_size - 2 * (int)sizeof(sljit_w)), DR(SLJIT_LOCALS_REG))); + + FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); + if (compiler->local_size <= SIMM_MAX) + return push_inst(compiler, ADDIU_W | S(REAL_STACK_PTR) | T(REAL_STACK_PTR) | IMM(compiler->local_size), UNMOVABLE_INS); + else + return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(REAL_STACK_PTR), UNMOVABLE_INS); +} + +#undef STACK_STORE +#undef STACK_LOAD + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define ARCH_DEPEND(a, b) a +#else +#define ARCH_DEPEND(a, b) b +#endif + +static SLJIT_CONST sljit_ins data_transfer_insts[16] = { +/* s u w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */), +/* s u b */ HI(40) /* sb */, +/* s u h */ HI(41) /* sh*/, +/* s u i */ HI(43) /* sw */, + +/* s s w */ ARCH_DEPEND(HI(43) /* sw */, HI(63) /* sd */), +/* s s b */ HI(40) /* sb */, +/* s s h */ HI(41) /* sh*/, +/* s s i */ HI(43) /* sw */, + +/* l u w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */), +/* l u b */ HI(36) /* lbu */, +/* l u h */ HI(37) /* lhu */, +/* l u i */ ARCH_DEPEND(HI(35) /* lw */, HI(39) /* lwu */), + +/* l s w */ ARCH_DEPEND(HI(35) /* lw */, HI(55) /* ld */), +/* l s b */ HI(32) /* lb */, +/* l s h */ HI(33) /* lh */, +/* l s i */ HI(35) /* lw */, +}; + +/* reg_ar is an absoulute register! */ + +/* Can perform an operation using at most 1 instruction. */ +static int getput_arg_fast(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw) +{ + SLJIT_ASSERT(arg & SLJIT_MEM); + + if (!(flags & WRITE_BACK) && !(arg & 0xf0) && argw <= SIMM_MAX && argw >= SIMM_MIN) { + /* Works for both absoulte and relative addresses. */ + if (SLJIT_UNLIKELY(flags & ARG_TEST)) + return 1; + FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & 0xf) | TA(reg_ar) | IMM(argw), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS)); + return -1; + } + return (flags & ARG_TEST) ? SLJIT_SUCCESS : 0; +} + +/* See getput_arg below. + Note: can_cache is called only for binary operators. Those + operators always uses word arguments without write back. */ +static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + if (!(next_arg & SLJIT_MEM)) + return 0; + + /* Simple operation except for updates. */ + if (arg & 0xf0) { + argw &= 0x3; + next_argw &= 0x3; + if (argw && argw == next_argw && (arg == next_arg || (arg & 0xf0) == (next_arg & 0xf0))) + return 1; + return 0; + } + + if (arg == next_arg) { + if (((sljit_uw)(next_argw - argw) <= SIMM_MAX && (sljit_uw)(next_argw - argw) >= SIMM_MIN)) + return 1; + return 0; + } + + return 0; +} + +/* Emit the necessary instructions. See can_cache above. */ +static int getput_arg(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + int tmp_ar; + int base; + + SLJIT_ASSERT(arg & SLJIT_MEM); + if (!(next_arg & SLJIT_MEM)) { + next_arg = 0; + next_argw = 0; + } + + tmp_ar = (flags & LOAD_DATA) ? reg_ar : DR(TMP_REG3); + base = arg & 0xf; + + if (SLJIT_UNLIKELY(arg & 0xf0)) { + argw &= 0x3; + if ((flags & WRITE_BACK) && reg_ar == DR(base)) { + SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar); + FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + reg_ar = DR(TMP_REG1); + } + + /* Using the cache. */ + if (argw == compiler->cache_argw) { + if (!(flags & WRITE_BACK)) { + if (arg == compiler->cache_arg) + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) { + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + } + else { + if ((SLJIT_MEM | (arg & 0xf0)) == compiler->cache_arg) { + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + } + } + + if (SLJIT_UNLIKELY(argw)) { + compiler->cache_arg = SLJIT_MEM | (arg & 0xf0); + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, SLL_W | T((arg >> 4) & 0xf) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3))); + } + + if (!(flags & WRITE_BACK)) { + if (arg == next_arg && argw == (next_argw & 0x3)) { + compiler->cache_arg = arg; + compiler->cache_argw = argw; + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3))); + tmp_ar = DR(TMP_REG3); + } + else + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | DA(tmp_ar), tmp_ar)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? ((arg >> 4) & 0xf) : TMP_REG3) | D(base), DR(base))); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + + if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) { + /* Update only applies if a base register exists. */ + if (reg_ar == DR(base)) { + SLJIT_ASSERT(!(flags & LOAD_DATA) && DR(TMP_REG1) != reg_ar); + if (argw <= SIMM_MAX && argw >= SIMM_MIN) { + FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar) | IMM(argw), MOVABLE_INS)); + if (argw) + return push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base)); + return SLJIT_SUCCESS; + } + FAIL_IF(push_inst(compiler, ADDU_W | SA(reg_ar) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); + reg_ar = DR(TMP_REG1); + } + + if (argw <= SIMM_MAX && argw >= SIMM_MIN) { + if (argw) + FAIL_IF(push_inst(compiler, ADDIU_W | S(base) | T(base) | IMM(argw), DR(base))); + } + else { + if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { + if (argw != compiler->cache_argw) { + FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); + compiler->cache_argw = argw; + } + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); + } + else { + compiler->cache_arg = SLJIT_MEM; + compiler->cache_argw = argw; + FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); + FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(base), DR(base))); + } + } + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(base) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { + if (argw != compiler->cache_argw) { + FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); + compiler->cache_argw = argw; + } + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + + if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) { + if (argw != compiler->cache_argw) + FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3))); + } + else { + compiler->cache_arg = SLJIT_MEM; + FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); + } + compiler->cache_argw = argw; + + if (!base) + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + + if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) { + compiler->cache_arg = arg; + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3))); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); + } + + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar)); + return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), (flags & LOAD_DATA) ? reg_ar : MOVABLE_INS); +} + +static SLJIT_INLINE int emit_op_mem(struct sljit_compiler *compiler, int flags, int reg_ar, int arg, sljit_w argw) +{ + if (getput_arg_fast(compiler, flags, reg_ar, arg, argw)) + return compiler->error; + compiler->cache_arg = 0; + compiler->cache_argw = 0; + return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0); +} + +static int emit_op(struct sljit_compiler *compiler, int op, int flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* arg1 goes to TMP_REG1 or src reg + arg2 goes to TMP_REG2, imm or src reg + TMP_REG3 can be used for caching + result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + int dst_r = TMP_REG2; + int src1_r; + sljit_w src2_r = 0; + int sugg_src2_r = TMP_REG2; + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REG3) { + dst_r = dst; + flags |= REG_DEST; + if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) + sugg_src2_r = dst_r; + } + else if (dst == SLJIT_UNUSED) { + if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM)) + return SLJIT_SUCCESS; + if (GET_FLAGS(op)) + flags |= UNUSED_DEST; + } + else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw)) + flags |= SLOW_DEST; + + if (flags & IMM_OP) { + if ((src2 & SLJIT_IMM) && src2w) { + if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN)) + || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) { + flags |= SRC2_IMM; + src2_r = src2w; + } + } + if ((src1 & SLJIT_IMM) && src1w && (flags & CUMULATIVE_OP) && !(flags & SRC2_IMM)) { + if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN)) + || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) { + flags |= SRC2_IMM; + src2_r = src1w; + + /* And swap arguments. */ + src1 = src2; + src1w = src2w; + src2 = SLJIT_IMM; + /* src2w = src2_r unneeded. */ + } + } + } + + /* Source 1. */ + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= TMP_REG3) { + src1_r = src1; + flags |= REG1_SOURCE; + } + else if (src1 & SLJIT_IMM) { + if (src1w) { + FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); + src1_r = TMP_REG1; + } + else + src1_r = 0; + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC1; + src1_r = TMP_REG1; + } + + /* Source 2. */ + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REG3) { + src2_r = src2; + flags |= REG2_SOURCE; + if (!(flags & REG_DEST) && GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) + dst_r = src2_r; + } + else if (src2 & SLJIT_IMM) { + if (!(flags & SRC2_IMM)) { + if (src2w || (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI)) { + FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w)); + src2_r = sugg_src2_r; + } + else + src2_r = 0; + } + } + else { + if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w)) + FAIL_IF(compiler->error); + else + flags |= SLOW_SRC2; + src2_r = sugg_src2_r; + } + + if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { + SLJIT_ASSERT(src2_r == TMP_REG2); + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw)); + } + } + else if (flags & SLOW_SRC1) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw)); + else if (flags & SLOW_SRC2) + FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw)); + + FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + + if (dst & SLJIT_MEM) { + if (!(flags & SLOW_DEST)) { + getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw); + return compiler->error; + } + return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + CHECK_ERROR(); + check_sljit_emit_op0(compiler, op); + + op = GET_OPCODE(op); + switch (op) { + case SLJIT_BREAKPOINT: + return push_inst(compiler, BREAK, UNMOVABLE_INS); + case SLJIT_NOP: + return push_inst(compiler, NOP, UNMOVABLE_INS); + case SLJIT_UMUL: + case SLJIT_SMUL: + FAIL_IF(push_inst(compiler, (op == SLJIT_UMUL ? MULTU : MULT) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1))); + return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2)); + case SLJIT_UDIV: + case SLJIT_SDIV: +#if !(defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); +#endif + FAIL_IF(push_inst(compiler, (op == SLJIT_UDIV ? DIVU : DIV) | S(SLJIT_TEMPORARY_REG1) | T(SLJIT_TEMPORARY_REG2), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_TEMPORARY_REG1), DR(SLJIT_TEMPORARY_REG1))); + return push_inst(compiler, MFHI | D(SLJIT_TEMPORARY_REG2), DR(SLJIT_TEMPORARY_REG2)); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #define inp_flags 0 +#endif + + CHECK_ERROR(); + check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + + SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_UI: + return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_SI: + return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_UB: + return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOV_SB: + return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOV_UH: + return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOV_SH: + return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_MOVU: + return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_UI: + return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_SI: + return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_UB: + return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOVU_SB: + return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOVU_UH: + return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOVU_SH: + return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_NOT: + return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_NEG: + return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), inp_flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); + + case SLJIT_CLZ: + return emit_op(compiler, op, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw); + } + + return SLJIT_SUCCESS; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #undef inp_flags +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #define inp_flags 0 +#endif + + CHECK_ERROR(); + check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + case SLJIT_ADDC: + return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SUB: + case SLJIT_SUBC: + return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_MUL: + return emit_op(compiler, op, inp_flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + return emit_op(compiler, op, inp_flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SHL: + case SLJIT_LSHR: + case SLJIT_ASHR: +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + if (src2 & SLJIT_IMM) + src2w &= 0x1f; +#else + if (src2 & SLJIT_IMM) + src2w &= 0x3f; +#endif + return emit_op(compiler, op, inp_flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w); + } + + return SLJIT_SUCCESS; +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) + #undef inp_flags +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + check_sljit_get_register_index(reg); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + CHECK_ERROR(); + check_sljit_emit_op_custom(compiler, instruction, size); + SLJIT_ASSERT(size == 4); + + return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ +#if (defined SLJIT_QEMU && SLJIT_QEMU) + /* Qemu says fir is 0 by default. */ + return 1; +#elif defined(__GNUC__) + sljit_w fir; + asm ("cfc1 %0, $0" : "=r"(fir)); + return (fir >> 22) & 0x1; +#else +#error "FIR check is not implemented for this architecture" +#endif +} + +static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw) +{ + int hi_reg; + + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* Fast loads and stores. */ + if (!(arg & 0xf0)) { + /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */ + if (argw <= SIMM_MAX && argw >= SIMM_MIN) + return push_inst(compiler, (load ? LDC1 : SDC1) | S(arg & 0xf) | FT(fpu_reg) | IMM(argw), MOVABLE_INS); + } + + if (arg & 0xf0) { + argw &= 0x3; + hi_reg = (arg >> 4) & 0xf; + if (argw) { + FAIL_IF(push_inst(compiler, SLL_W | T(hi_reg) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1))); + hi_reg = TMP_REG1; + } + FAIL_IF(push_inst(compiler, ADDU_W | S(hi_reg) | T(arg & 0xf) | D(TMP_REG1), DR(TMP_REG1))); + return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG1) | FT(fpu_reg) | IMM(0), MOVABLE_INS); + } + + /* Use cache. */ + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) + return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(argw - compiler->cache_argw), MOVABLE_INS); + + /* Put value to cache. */ + compiler->cache_arg = arg; + compiler->cache_argw = argw; + + FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw)); + if (arg & 0xf) + FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(arg & 0xf) | D(TMP_REG3), DR(TMP_REG3))); + return push_inst(compiler, (load ? LDC1 : SDC1) | S(TMP_REG3) | FT(fpu_reg) | IMM(0), MOVABLE_INS); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int dst_fr; + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (GET_OPCODE(op) == SLJIT_FCMP) { + if (dst > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw)); + dst = TMP_FREG1; + } + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw)); + src = TMP_FREG2; + } + + /* src and dst are swapped. */ + if (op & SLJIT_SET_E) { + FAIL_IF(push_inst(compiler, C_UEQ_D | FT(src) | FS(dst), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, CFC1 | TA(EQUAL_FLAG) | DA(FCSR_REG), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, SRL | TA(EQUAL_FLAG) | DA(EQUAL_FLAG) | SH_IMM(23), EQUAL_FLAG)); + FAIL_IF(push_inst(compiler, ANDI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG)); + } + if (op & SLJIT_SET_S) { + /* Mixing the instructions for the two checks. */ + FAIL_IF(push_inst(compiler, C_ULT_D | FT(src) | FS(dst), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, CFC1 | TA(ULESS_FLAG) | DA(FCSR_REG), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, C_ULT_D | FT(dst) | FS(src), UNMOVABLE_INS)); + FAIL_IF(push_inst(compiler, SRL | TA(ULESS_FLAG) | DA(ULESS_FLAG) | SH_IMM(23), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, ANDI | SA(ULESS_FLAG) | TA(ULESS_FLAG) | IMM(1), ULESS_FLAG)); + FAIL_IF(push_inst(compiler, CFC1 | TA(UGREATER_FLAG) | DA(FCSR_REG), UGREATER_FLAG)); + FAIL_IF(push_inst(compiler, SRL | TA(UGREATER_FLAG) | DA(UGREATER_FLAG) | SH_IMM(23), UGREATER_FLAG)); + FAIL_IF(push_inst(compiler, ANDI | SA(UGREATER_FLAG) | TA(UGREATER_FLAG) | IMM(1), UGREATER_FLAG)); + } + return push_inst(compiler, C_UN_D | FT(src) | FS(dst), FCSR_FCC); + } + + dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw)); + src = dst_fr; + } + + switch (op) { + case SLJIT_FMOV: + if (src != dst_fr && dst_fr != TMP_FREG1) + FAIL_IF(push_inst(compiler, MOV_D | FS(src) | FD(dst_fr), MOVABLE_INS)); + break; + case SLJIT_FNEG: + FAIL_IF(push_inst(compiler, NEG_D | FS(src) | FD(dst_fr), MOVABLE_INS)); + break; + case SLJIT_FABS: + FAIL_IF(push_inst(compiler, ABS_D | FS(src) | FD(dst_fr), MOVABLE_INS)); + break; + } + + if (dst_fr == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_fr; + + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src2 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); + src2 = TMP_FREG2; + } + + if (src1 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); + src1 = TMP_FREG1; + } + + switch (op) { + case SLJIT_FADD: + FAIL_IF(push_inst(compiler, ADD_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS)); + break; + + case SLJIT_FSUB: + FAIL_IF(push_inst(compiler, SUB_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS)); + break; + + case SLJIT_FMUL: + FAIL_IF(push_inst(compiler, MUL_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS)); + break; + + case SLJIT_FDIV: + FAIL_IF(push_inst(compiler, DIV_D | FT(src2) | FS(src1) | FD(dst_fr), MOVABLE_INS)); + break; + } + + if (dst_fr == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + compiler->has_locals = local_size > 0; + local_size += (saveds + 2 + 4) * sizeof(sljit_w); + compiler->local_size = (local_size + 15) & ~0xf; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst)); + else if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); + else if (src & SLJIT_MEM) + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); + else if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, RETURN_ADDR_REG, srcw)); + + FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); + return push_inst(compiler, NOP, UNMOVABLE_INS); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + check_sljit_emit_label(compiler); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + compiler->delay_slot = UNMOVABLE_INS; + return label; +} + +#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) +#define JUMP_LENGTH 4 +#else +#define JUMP_LENGTH 7 +#endif + +#define BR_Z(src) \ + inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \ + flags = IS_BIT26_COND; \ + delay_check = src; + +#define BR_NZ(src) \ + inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \ + flags = IS_BIT26_COND; \ + delay_check = src; + +#define BR_T() \ + inst = BC1T | JUMP_LENGTH; \ + flags = IS_BIT16_COND; \ + delay_check = FCSR_FCC; + +#define BR_F() \ + inst = BC1F | JUMP_LENGTH; \ + flags = IS_BIT16_COND; \ + delay_check = FCSR_FCC; + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + struct sljit_jump *jump; + sljit_ins inst; + int flags = 0; + int delay_check = UNMOVABLE_INS; + + CHECK_ERROR_PTR(); + check_sljit_emit_jump(compiler, type); + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_FLOAT_NOT_EQUAL: + BR_NZ(EQUAL_FLAG); + break; + case SLJIT_C_NOT_EQUAL: + case SLJIT_C_FLOAT_EQUAL: + BR_Z(EQUAL_FLAG); + break; + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + BR_Z(ULESS_FLAG); + break; + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + BR_NZ(ULESS_FLAG); + break; + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + BR_Z(UGREATER_FLAG); + break; + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + BR_NZ(UGREATER_FLAG); + break; + case SLJIT_C_SIG_LESS: + BR_Z(LESS_FLAG); + break; + case SLJIT_C_SIG_GREATER_EQUAL: + BR_NZ(LESS_FLAG); + break; + case SLJIT_C_SIG_GREATER: + BR_Z(GREATER_FLAG); + break; + case SLJIT_C_SIG_LESS_EQUAL: + BR_NZ(GREATER_FLAG); + break; + case SLJIT_C_OVERFLOW: + case SLJIT_C_MUL_OVERFLOW: + BR_Z(OVERFLOW_FLAG); + break; + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + BR_NZ(OVERFLOW_FLAG); + break; + case SLJIT_C_FLOAT_NAN: + BR_F(); + break; + case SLJIT_C_FLOAT_NOT_NAN: + BR_T(); + break; + default: + /* Not conditional branch. */ + inst = 0; + break; + } + + jump->flags |= flags; + if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check)) + jump->flags |= IS_MOVABLE; + + if (inst) + PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS)); + + PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + if (type <= SLJIT_JUMP) { + PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + } else { + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + /* Cannot be optimized out if type is >= CALL0. */ + jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0); + PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + jump->addr = compiler->size; + /* A NOP if type < CALL1. */ + PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS)); + } + return jump; +} + +#define RESOLVE_IMM1() \ + if (src1 & SLJIT_IMM) { \ + if (src1w) { \ + PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \ + src1 = TMP_REG1; \ + } \ + else \ + src1 = 0; \ + } + +#define RESOLVE_IMM2() \ + if (src2 & SLJIT_IMM) { \ + if (src2w) { \ + PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \ + src2 = TMP_REG2; \ + } \ + else \ + src2 = 0; \ + } + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + struct sljit_jump *jump; + int flags; + sljit_ins inst; + + CHECK_ERROR_PTR(); + check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + flags = ((type & SLJIT_INT_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA; + if (src1 & SLJIT_MEM) { + if (getput_arg_fast(compiler, flags, DR(TMP_REG1), src1, src1w)) + PTR_FAIL_IF(compiler->error); + else + PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w)); + src1 = TMP_REG1; + } + if (src2 & SLJIT_MEM) { + if (getput_arg_fast(compiler, flags, DR(TMP_REG2), src2, src2w)) + PTR_FAIL_IF(compiler->error); + else + PTR_FAIL_IF(getput_arg(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0)); + src2 = TMP_REG2; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + if (type <= SLJIT_C_NOT_EQUAL) { + RESOLVE_IMM1(); + RESOLVE_IMM2(); + jump->flags |= IS_BIT26_COND; + if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2))) + jump->flags |= IS_MOVABLE; + PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_C_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS)); + } + else if (type >= SLJIT_C_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) { + inst = NOP; + if ((src1 & SLJIT_IMM) && (src1w == 0)) { + RESOLVE_IMM2(); + switch (type) { + case SLJIT_C_SIG_LESS: + inst = BLEZ; + jump->flags |= IS_BIT26_COND; + break; + case SLJIT_C_SIG_GREATER_EQUAL: + inst = BGTZ; + jump->flags |= IS_BIT26_COND; + break; + case SLJIT_C_SIG_GREATER: + inst = BGEZ; + jump->flags |= IS_BIT16_COND; + break; + case SLJIT_C_SIG_LESS_EQUAL: + inst = BLTZ; + jump->flags |= IS_BIT16_COND; + break; + } + src1 = src2; + } + else { + RESOLVE_IMM1(); + switch (type) { + case SLJIT_C_SIG_LESS: + inst = BGEZ; + jump->flags |= IS_BIT16_COND; + break; + case SLJIT_C_SIG_GREATER_EQUAL: + inst = BLTZ; + jump->flags |= IS_BIT16_COND; + break; + case SLJIT_C_SIG_GREATER: + inst = BLEZ; + jump->flags |= IS_BIT26_COND; + break; + case SLJIT_C_SIG_LESS_EQUAL: + inst = BGTZ; + jump->flags |= IS_BIT26_COND; + break; + } + } + PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS)); + } + else { + if (type == SLJIT_C_LESS || type == SLJIT_C_GREATER_EQUAL || type == SLJIT_C_SIG_LESS || type == SLJIT_C_SIG_GREATER_EQUAL) { + RESOLVE_IMM1(); + if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN) + PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1))); + else { + RESOLVE_IMM2(); + PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1))); + } + type = (type == SLJIT_C_LESS || type == SLJIT_C_SIG_LESS) ? SLJIT_C_NOT_EQUAL : SLJIT_C_EQUAL; + } + else { + RESOLVE_IMM2(); + if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN) + PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1))); + else { + RESOLVE_IMM1(); + PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_C_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1))); + } + type = (type == SLJIT_C_GREATER || type == SLJIT_C_SIG_GREATER) ? SLJIT_C_NOT_EQUAL : SLJIT_C_EQUAL; + } + + jump->flags |= IS_BIT26_COND; + PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_C_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS)); + } + + PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + return jump; +} + +#undef RESOLVE_IMM1 +#undef RESOLVE_IMM2 + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + struct sljit_jump *jump; + sljit_ins inst; + int if_true; + + CHECK_ERROR_PTR(); + check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (src1 > SLJIT_FLOAT_REG4) { + PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); + src1 = TMP_FREG1; + } + if (src2 > SLJIT_FLOAT_REG4) { + PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); + src2 = TMP_FREG2; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + jump->flags |= IS_BIT16_COND; + type &= 0xff; + + switch (type) { + case SLJIT_C_FLOAT_EQUAL: + inst = C_UEQ_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NOT_EQUAL: + inst = C_UEQ_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_LESS: + inst = C_ULT_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_GREATER_EQUAL: + inst = C_ULT_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_GREATER: + inst = C_ULE_D; + if_true = 0; + break; + case SLJIT_C_FLOAT_LESS_EQUAL: + inst = C_ULE_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NAN: + inst = C_UN_D; + if_true = 1; + break; + case SLJIT_C_FLOAT_NOT_NAN: + default: /* Make compilers happy. */ + inst = C_UN_D; + if_true = 0; + break; + } + + PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS)); + /* Intentionally the other opcode. */ + PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS)); + PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS)); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + return jump; +} + +#undef JUMP_LENGTH +#undef BR_Z +#undef BR_NZ +#undef BR_T +#undef BR_F + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + int src_r = TMP_REG2; + struct sljit_jump *jump = NULL; + + CHECK_ERROR(); + check_sljit_emit_ijump(compiler, type, src, srcw); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) { + if (DR(src) != 4) + src_r = src; + else + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + } + + if (type >= SLJIT_CALL0) { + SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2); + if (src & (SLJIT_IMM | SLJIT_MEM)) { + if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw)); + else { + SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM)); + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + } + FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + /* We need an extra instruction in any case. */ + return push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), UNMOVABLE_INS); + } + + /* Register input. */ + if (type >= SLJIT_CALL1) + FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_TEMPORARY_REG1) | TA(0) | DA(4), 4)); + FAIL_IF(push_inst(compiler, JALR | S(src_r) | DA(RETURN_ADDR_REG), UNMOVABLE_INS)); + return push_inst(compiler, ADDU_W | S(src_r) | TA(0) | D(PIC_ADDR_REG), UNMOVABLE_INS); + } + + if (src & SLJIT_IMM) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0)); + jump->u.target = srcw; + + if (compiler->delay_slot != UNMOVABLE_INS) + jump->flags |= IS_MOVABLE; + + FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + } + else if (src & SLJIT_MEM) + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + + FAIL_IF(push_inst(compiler, JR | S(src_r), UNMOVABLE_INS)); + if (jump) + jump->addr = compiler->size; + FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + int sugg_dst_ar, dst_ar; + + CHECK_ERROR(); + check_sljit_emit_cond_value(compiler, op, dst, dstw, type); + + if (dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + sugg_dst_ar = DR((op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2); + + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_NOT_EQUAL: + FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); + 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: + 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: + dst_ar = UGREATER_FLAG; + break; + case SLJIT_C_SIG_LESS: + case SLJIT_C_SIG_GREATER_EQUAL: + dst_ar = LESS_FLAG; + break; + case SLJIT_C_SIG_GREATER: + case SLJIT_C_SIG_LESS_EQUAL: + dst_ar = GREATER_FLAG; + break; + case SLJIT_C_OVERFLOW: + case SLJIT_C_NOT_OVERFLOW: + dst_ar = OVERFLOW_FLAG; + break; + case SLJIT_C_MUL_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + FAIL_IF(push_inst(compiler, SLTIU | SA(OVERFLOW_FLAG) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); + 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; + + case SLJIT_C_FLOAT_NAN: + case SLJIT_C_FLOAT_NOT_NAN: + FAIL_IF(push_inst(compiler, CFC1 | TA(sugg_dst_ar) | DA(FCSR_REG), sugg_dst_ar)); + FAIL_IF(push_inst(compiler, SRL | TA(sugg_dst_ar) | DA(sugg_dst_ar) | SH_IMM(23), sugg_dst_ar)); + FAIL_IF(push_inst(compiler, ANDI | SA(sugg_dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); + dst_ar = sugg_dst_ar; + break; + + default: + SLJIT_ASSERT_STOP(); + dst_ar = sugg_dst_ar; + break; + } + + if (type & 0x1) { + FAIL_IF(push_inst(compiler, XORI | SA(dst_ar) | TA(sugg_dst_ar) | IMM(1), sugg_dst_ar)); + dst_ar = sugg_dst_ar; + } + + if (GET_OPCODE(op) == SLJIT_OR) { + if (DR(TMP_REG2) != dst_ar) + FAIL_IF(push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2))); + return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, dst, dstw, TMP_REG2, 0); + } + + if (dst & SLJIT_MEM) + return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw); + + if (sugg_dst_ar != dst_ar) + return push_inst(compiler, ADDU_W | SA(dst_ar) | TA(0) | DA(sugg_dst_ar), sugg_dst_ar); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + struct sljit_const *const_; + int reg; + + CHECK_ERROR_PTR(); + check_sljit_emit_const(compiler, dst, dstw, init_value); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + + PTR_FAIL_IF(emit_const(compiler, reg, init_value)); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); + return const_; +} diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_32.c b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c new file mode 100644 index 0000000000..82d0508ac1 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativePPC_32.c @@ -0,0 +1,262 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ppc 32-bit arch dependent functions. */ + +static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm) +{ + if (imm <= SIMM_MAX && imm >= SIMM_MIN) + return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); + + if (!(imm & ~0xffff)) + return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm)); + + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); + return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; +} + +#define INS_CLEAR_LEFT(dst, src, from) \ + (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1)) + +static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags, + int dst, int src1, int src2) +{ + switch (op) { + case SLJIT_ADD: + if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM2) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM4) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); + return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); + } + if (!(flags & ALT_SET_FLAGS)) + return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); + return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + + case SLJIT_ADDC: + if (flags & ALT_FORM1) { + FAIL_IF(push_inst(compiler, MFXER | S(0))); + FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2))); + return push_inst(compiler, MTXER | S(0)); + } + return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); + + case SLJIT_SUB: + if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); + } + if (flags & (ALT_FORM2 | ALT_FORM3)) { + SLJIT_ASSERT(src2 == TMP_REG2); + if (flags & ALT_FORM2) + FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm)); + if (flags & ALT_FORM3) + return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm); + return SLJIT_SUCCESS; + } + if (flags & (ALT_FORM4 | ALT_FORM5)) { + if (flags & ALT_FORM4) + FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); + if (flags & ALT_FORM5) + FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2))); + return SLJIT_SUCCESS; + } + if (!(flags & ALT_SET_FLAGS)) + return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); + if (flags & ALT_FORM6) + FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); + return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + + case SLJIT_SUBC: + if (flags & ALT_FORM1) { + FAIL_IF(push_inst(compiler, MFXER | S(0))); + FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1))); + return push_inst(compiler, MTXER | S(0)); + } + return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); + + case SLJIT_MUL: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); + } + return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); + + case SLJIT_AND: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); + } + return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_OR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + } + return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_XOR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + } + return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_SHL: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + compiler->imm &= 0x1f; + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + } + return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_LSHR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + compiler->imm &= 0x1f; + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + } + return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ASHR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + compiler->imm &= 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + } + return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_MOV: + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + SLJIT_ASSERT(src1 == TMP_REG1); + if (dst != src2) + return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UB: + case SLJIT_MOV_SB: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SB) + return push_inst(compiler, EXTSB | S(src2) | A(dst)); + return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); + } + else if ((flags & REG_DEST) && op == SLJIT_MOV_SB) + return push_inst(compiler, EXTSB | S(src2) | A(dst)); + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UH: + case SLJIT_MOV_SH: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SH) + return push_inst(compiler, EXTSH | S(src2) | A(dst)); + return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); + } + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_NOT: + SLJIT_ASSERT(src1 == TMP_REG1); + return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); + + case SLJIT_NEG: + SLJIT_ASSERT(src1 == TMP_REG1); + return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1); + return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); + } + + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value) +{ + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16))); + return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 2); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 2); +} diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_64.c b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c new file mode 100644 index 0000000000..cc2ae37eb9 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativePPC_64.c @@ -0,0 +1,428 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ppc 64-bit arch dependent functions. */ + +#ifdef __GNUC__ +#define ASM_SLJIT_CLZ(src, dst) \ + asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) ) +#else +#error "Must implement count leading zeroes" +#endif + +#define RLDI(dst, src, sh, mb, type) \ + (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20)) + +#define PUSH_RLDICR(reg, shift) \ + push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1)) + +static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm) +{ + sljit_uw tmp; + sljit_uw shift; + sljit_uw tmp2; + sljit_uw shift2; + + if (imm <= SIMM_MAX && imm >= SIMM_MIN) + return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); + + if (!(imm & ~0xffff)) + return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm)); + + if (imm <= SLJIT_W(0x7fffffff) && imm >= SLJIT_W(-0x80000000)) { + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); + return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; + } + + /* Count leading zeroes. */ + tmp = (imm >= 0) ? imm : ~imm; + ASM_SLJIT_CLZ(tmp, shift); + SLJIT_ASSERT(shift > 0); + shift--; + tmp = (imm << shift); + + if ((tmp & ~0xffff000000000000ul) == 0) { + FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); + shift += 15; + return PUSH_RLDICR(reg, shift); + } + + if ((tmp & ~0xffffffff00000000ul) == 0) { + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48))); + FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); + shift += 31; + return PUSH_RLDICR(reg, shift); + } + + /* Cut out the 16 bit from immediate. */ + shift += 15; + tmp2 = imm & ((1ul << (63 - shift)) - 1); + + if (tmp2 <= 0xffff) { + FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); + FAIL_IF(PUSH_RLDICR(reg, shift)); + return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2); + } + + if (tmp2 <= 0xffffffff) { + FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); + FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16))); + return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; + } + + ASM_SLJIT_CLZ(tmp2, shift2); + tmp2 <<= shift2; + + if ((tmp2 & ~0xffff000000000000ul) == 0) { + FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); + shift2 += 15; + shift += (63 - shift2); + FAIL_IF(PUSH_RLDICR(reg, shift)); + FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48))); + return PUSH_RLDICR(reg, shift2); + } + + /* The general version. */ + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48))); + FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32))); + FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); + return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); +} + +/* Simplified mnemonics: clrldi. */ +#define INS_CLEAR_LEFT(dst, src, from) \ + (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5)) + +/* Sign extension for integer operations. */ +#define UN_EXTS() \ + if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \ + FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ + src2 = TMP_REG2; \ + } + +#define BIN_EXTS() \ + if (flags & ALT_SIGN_EXT) { \ + if (flags & REG1_SOURCE) { \ + FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ + src1 = TMP_REG1; \ + } \ + if (flags & REG2_SOURCE) { \ + FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ + src2 = TMP_REG2; \ + } \ + } + +#define BIN_IMM_EXTS() \ + if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \ + FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ + src1 = TMP_REG1; \ + } + +static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags, + int dst, int src1, int src2) +{ + switch (op) { + case SLJIT_ADD: + if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM2) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + BIN_IMM_EXTS(); + return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); + } + if (flags & ALT_FORM4) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); + return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); + } + if (!(flags & ALT_SET_FLAGS)) + return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); + BIN_EXTS(); + return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); + + case SLJIT_ADDC: + if (flags & ALT_FORM1) { + FAIL_IF(push_inst(compiler, MFXER | S(0))); + FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2))); + return push_inst(compiler, MTXER | S(0)); + } + BIN_EXTS(); + return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); + + case SLJIT_SUB: + if (flags & ALT_FORM1) { + /* Flags does not set: BIN_IMM_EXTS unnecessary. */ + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); + } + if (flags & (ALT_FORM2 | ALT_FORM3)) { + SLJIT_ASSERT(src2 == TMP_REG2); + if (flags & ALT_FORM2) + FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); + if (flags & ALT_FORM3) + return push_inst(compiler, CMPLI | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); + return SLJIT_SUCCESS; + } + if (flags & (ALT_FORM4 | ALT_FORM5)) { + if (flags & ALT_FORM4) + FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); + if (flags & ALT_FORM5) + return push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); + return SLJIT_SUCCESS; + } + if (!(flags & ALT_SET_FLAGS)) + return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); + BIN_EXTS(); + if (flags & ALT_FORM6) + FAIL_IF(push_inst(compiler, CMPL | CRD(4 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); + return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); + + case SLJIT_SUBC: + if (flags & ALT_FORM1) { + FAIL_IF(push_inst(compiler, MFXER | S(0))); + FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1))); + return push_inst(compiler, MTXER | S(0)); + } + BIN_EXTS(); + return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); + + case SLJIT_MUL: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); + } + BIN_EXTS(); + if (flags & ALT_FORM2) + return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); + return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1)); + + case SLJIT_AND: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); + } + return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_OR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); + return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + } + return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_XOR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM2) { + SLJIT_ASSERT(src2 == TMP_REG2); + return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); + } + if (flags & ALT_FORM3) { + SLJIT_ASSERT(src2 == TMP_REG2); + FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); + return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); + } + return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_SHL: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + if (flags & ALT_FORM2) { + compiler->imm &= 0x1f; + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); + } + else { + compiler->imm &= 0x3f; + return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); + } + } + if (flags & ALT_FORM2) + return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); + return push_inst(compiler, SLD | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_LSHR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + if (flags & ALT_FORM2) { + compiler->imm &= 0x1f; + return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); + } + else { + compiler->imm &= 0x3f; + return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); + } + } + if (flags & ALT_FORM2) + return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); + return push_inst(compiler, SRD | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_ASHR: + if (flags & ALT_FORM1) { + SLJIT_ASSERT(src2 == TMP_REG2); + if (flags & ALT_FORM2) { + compiler->imm &= 0x1f; + return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); + } + else { + compiler->imm &= 0x3f; + return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); + } + } + if (flags & ALT_FORM2) + return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); + return push_inst(compiler, SRAD | RC(flags) | S(src1) | A(dst) | B(src2)); + + case SLJIT_MOV: + SLJIT_ASSERT(src1 == TMP_REG1); + if (dst != src2) + return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SI) + return push_inst(compiler, EXTSW | S(src2) | A(dst)); + return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0)); + } + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UB: + case SLJIT_MOV_SB: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SB) + return push_inst(compiler, EXTSB | S(src2) | A(dst)); + return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); + } + else if ((flags & REG_DEST) && op == SLJIT_MOV_SB) + return push_inst(compiler, EXTSB | S(src2) | A(dst)); + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_MOV_UH: + case SLJIT_MOV_SH: + SLJIT_ASSERT(src1 == TMP_REG1); + if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { + if (op == SLJIT_MOV_SH) + return push_inst(compiler, EXTSH | S(src2) | A(dst)); + return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); + } + else if (dst != src2) + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; + + case SLJIT_NOT: + SLJIT_ASSERT(src1 == TMP_REG1); + UN_EXTS(); + return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); + + case SLJIT_NEG: + SLJIT_ASSERT(src1 == TMP_REG1); + UN_EXTS(); + return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); + + case SLJIT_CLZ: + SLJIT_ASSERT(src1 == TMP_REG1); + if (flags & ALT_FORM1) + return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); + return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst)); + } + + SLJIT_ASSERT_STOP(); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value) +{ + FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48))); + FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32))); + FAIL_IF(PUSH_RLDICR(reg, 31)); + FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); + return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff); + inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff); + inst[4] = (inst[4] & 0xffff0000) | (new_addr & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 5); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + sljit_ins *inst = (sljit_ins*)addr; + + inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); + inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); + inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); + inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff); + SLJIT_CACHE_FLUSH(inst, inst + 5); +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func) +{ + sljit_w* ptrs; + if (func_ptr) + *func_ptr = (void*)context; + ptrs = (sljit_w*)func; + context->addr = addr ? addr : ptrs[0]; + context->r2 = ptrs[1]; + context->r11 = ptrs[2]; +} diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c new file mode 100644 index 0000000000..f0f191de1f --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c @@ -0,0 +1,1872 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ + return "PowerPC" SLJIT_CPUINFO; +} + +/* Length of an instruction word. + Both for ppc-32 and ppc-64. */ +typedef sljit_ui sljit_ins; + +static void ppc_cache_flush(sljit_ins *from, sljit_ins *to) +{ + while (from < to) { +#ifdef __GNUC__ + asm volatile ( "icbi 0, %0" : : "r"(from) ); +#else +#error "Must implement icbi" +#endif + from++; + } +} + +#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) +#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) +#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) +#define ZERO_REG (SLJIT_NO_REGISTERS + 4) +#define REAL_STACK_PTR (SLJIT_NO_REGISTERS + 5) + +#define TMP_FREG1 (SLJIT_FLOAT_REG4 + 1) +#define TMP_FREG2 (SLJIT_FLOAT_REG4 + 2) + +/* --------------------------------------------------------------------- */ +/* Instrucion forms */ +/* --------------------------------------------------------------------- */ +#define D(d) (reg_map[d] << 21) +#define S(s) (reg_map[s] << 21) +#define A(a) (reg_map[a] << 16) +#define B(b) (reg_map[b] << 11) +#define C(c) (reg_map[c] << 6) +#define FD(fd) ((fd) << 21) +#define FA(fa) ((fa) << 16) +#define FB(fb) ((fb) << 11) +#define FC(fc) ((fc) << 6) +#define IMM(imm) ((imm) & 0xffff) +#define CRD(d) ((d) << 21) + +/* Instruction bit sections. + OE and Rc flag (see ALT_SET_FLAGS). */ +#define OERC(flags) (((flags & ALT_SET_FLAGS) >> 10) | (flags & ALT_SET_FLAGS)) +/* Rc flag (see ALT_SET_FLAGS). */ +#define RC(flags) ((flags & ALT_SET_FLAGS) >> 10) +#define HI(opcode) ((opcode) << 26) +#define LO(opcode) ((opcode) << 1) + +#define ADD (HI(31) | LO(266)) +#define ADDC (HI(31) | LO(10)) +#define ADDE (HI(31) | LO(138)) +#define ADDI (HI(14)) +#define ADDIC (HI(13)) +#define ADDIS (HI(15)) +#define ADDME (HI(31) | LO(234)) +#define AND (HI(31) | LO(28)) +#define ANDI (HI(28)) +#define ANDIS (HI(29)) +#define Bx (HI(18)) +#define BCx (HI(16)) +#define BCCTR (HI(19) | LO(528) | (3 << 11)) +#define BLR (HI(19) | LO(16) | (0x14 << 21)) +#define CNTLZD (HI(31) | LO(58)) +#define CNTLZW (HI(31) | LO(26)) +#define CMP (HI(31) | LO(0)) +#define CMPI (HI(11)) +#define CMPL (HI(31) | LO(32)) +#define CMPLI (HI(10)) +#define CROR (HI(19) | LO(449)) +#define DIVD (HI(31) | LO(489)) +#define DIVDU (HI(31) | LO(457)) +#define DIVW (HI(31) | LO(491)) +#define DIVWU (HI(31) | LO(459)) +#define EXTSB (HI(31) | LO(954)) +#define EXTSH (HI(31) | LO(922)) +#define EXTSW (HI(31) | LO(986)) +#define FABS (HI(63) | LO(264)) +#define FADD (HI(63) | LO(21)) +#define FCMPU (HI(63) | LO(0)) +#define FDIV (HI(63) | LO(18)) +#define FMR (HI(63) | LO(72)) +#define FMUL (HI(63) | LO(25)) +#define FNEG (HI(63) | LO(40)) +#define FSUB (HI(63) | LO(20)) +#define LD (HI(58) | 0) +#define LFD (HI(50)) +#define LFDUX (HI(31) | LO(631)) +#define LFDX (HI(31) | LO(599)) +#define LWZ (HI(32)) +#define MFCR (HI(31) | LO(19)) +#define MFLR (HI(31) | LO(339) | 0x80000) +#define MFXER (HI(31) | LO(339) | 0x10000) +#define MTCTR (HI(31) | LO(467) | 0x90000) +#define MTLR (HI(31) | LO(467) | 0x80000) +#define MTXER (HI(31) | LO(467) | 0x10000) +#define MULHD (HI(31) | LO(73)) +#define MULHDU (HI(31) | LO(9)) +#define MULHW (HI(31) | LO(75)) +#define MULHWU (HI(31) | LO(11)) +#define MULLD (HI(31) | LO(233)) +#define MULLI (HI(7)) +#define MULLW (HI(31) | LO(235)) +#define NEG (HI(31) | LO(104)) +#define NOP (HI(24)) +#define NOR (HI(31) | LO(124)) +#define OR (HI(31) | LO(444)) +#define ORI (HI(24)) +#define ORIS (HI(25)) +#define RLDICL (HI(30)) +#define RLWINM (HI(21)) +#define SLD (HI(31) | LO(27)) +#define SLW (HI(31) | LO(24)) +#define SRAD (HI(31) | LO(794)) +#define SRADI (HI(31) | LO(413 << 1)) +#define SRAW (HI(31) | LO(792)) +#define SRAWI (HI(31) | LO(824)) +#define SRD (HI(31) | LO(539)) +#define SRW (HI(31) | LO(536)) +#define STD (HI(62) | 0) +#define STDU (HI(62) | 1) +#define STDUX (HI(31) | LO(181)) +#define STFD (HI(54)) +#define STFDUX (HI(31) | LO(759)) +#define STFDX (HI(31) | LO(727)) +#define STW (HI(36)) +#define STWU (HI(37)) +#define STWUX (HI(31) | LO(183)) +#define SUBF (HI(31) | LO(40)) +#define SUBFC (HI(31) | LO(8)) +#define SUBFE (HI(31) | LO(136)) +#define SUBFIC (HI(8)) +#define XOR (HI(31) | LO(316)) +#define XORI (HI(26)) +#define XORIS (HI(27)) + +#define SIMM_MAX (0x7fff) +#define SIMM_MIN (-0x8000) +#define UIMM_MAX (0xffff) + +/* SLJIT_LOCALS_REG is not the real stack register, since it must + point to the head of the stack chain. */ +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 6] = { + 0, 3, 4, 5, 6, 7, 29, 28, 27, 26, 25, 31, 8, 9, 10, 30, 1 +}; + +static int push_inst(struct sljit_compiler *compiler, sljit_ins ins) +{ + sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ptr); + *ptr = ins; + compiler->size++; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int optimize_jump(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code) +{ + sljit_w diff; + sljit_uw target_addr; + + if (jump->flags & SLJIT_REWRITABLE_JUMP) + return 0; + + if (jump->flags & JUMP_ADDR) + target_addr = jump->u.target; + else { + SLJIT_ASSERT(jump->flags & JUMP_LABEL); + target_addr = (sljit_uw)(code + jump->u.label->size); + } + diff = ((sljit_w)target_addr - (sljit_w)(code_ptr)) & ~0x3l; + + if (jump->flags & UNCOND_B) { + if (diff <= 0x01ffffff && diff >= -0x02000000) { + jump->flags |= PATCH_B; + return 1; + } + if (target_addr <= 0x03ffffff) { + jump->flags |= PATCH_B | ABSOLUTE_B; + return 1; + } + } + else { + if (diff <= 0x7fff && diff >= -0x8000) { + jump->flags |= PATCH_B; + return 1; + } + if (target_addr <= 0xffff) { + jump->flags |= PATCH_B | ABSOLUTE_B; + return 1; + } + } + return 0; +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_ins *code; + sljit_ins *code_ptr; + sljit_ins *buf_ptr; + sljit_ins *buf_end; + sljit_uw word_count; + sljit_uw addr; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + + CHECK_ERROR_PTR(); + check_sljit_generate_code(compiler); + reverse_buf(compiler); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins)); +#endif + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + word_count = 0; + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + do { + buf_ptr = (sljit_ins*)buf->memory; + buf_end = buf_ptr + (buf->used_size >> 2); + do { + *code_ptr = *buf_ptr++; + SLJIT_ASSERT(!label || label->size >= word_count); + SLJIT_ASSERT(!jump || jump->addr >= word_count); + SLJIT_ASSERT(!const_ || const_->addr >= word_count); + /* These structures are ordered by their address. */ + if (label && label->size == word_count) { + /* Just recording the address. */ + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + if (jump && jump->addr == word_count) { +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + jump->addr = (sljit_uw)(code_ptr - 3); +#else + jump->addr = (sljit_uw)(code_ptr - 6); +#endif + if (optimize_jump(jump, code_ptr, code)) { +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + code_ptr[-3] = code_ptr[0]; + code_ptr -= 3; +#else + code_ptr[-6] = code_ptr[0]; + code_ptr -= 6; +#endif + } + jump = jump->next; + } + if (const_ && const_->addr == word_count) { + /* Just recording the address. */ + const_->addr = (sljit_uw)code_ptr; + const_ = const_->next; + } + code_ptr ++; + word_count ++; + } while (buf_ptr < buf_end); + + buf = buf->next; + } while (buf); + + if (label && label->size == word_count) { + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + SLJIT_ASSERT(code_ptr - code <= (int)compiler->size - ((compiler->size & 0x1) ? 3 : 2)); +#else + SLJIT_ASSERT(code_ptr - code <= (int)compiler->size); +#endif + + jump = compiler->jumps; + while (jump) { + do { + addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + buf_ptr = (sljit_ins*)jump->addr; + if (jump->flags & PATCH_B) { + if (jump->flags & UNCOND_B) { + if (!(jump->flags & ABSOLUTE_B)) { + addr = addr - jump->addr; + SLJIT_ASSERT((sljit_w)addr <= 0x01ffffff && (sljit_w)addr >= -0x02000000); + *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1); + } + else { + SLJIT_ASSERT(addr <= 0x03ffffff); + *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1); + } + } + else { + if (!(jump->flags & ABSOLUTE_B)) { + addr = addr - jump->addr; + SLJIT_ASSERT((sljit_w)addr <= 0x7fff && (sljit_w)addr >= -0x8000); + *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001); + } + else { + addr = addr & ~0x3l; + SLJIT_ASSERT(addr <= 0xffff); + *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001); + } + + } + break; + } + /* Set the fields of immediate loads. */ +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff); + buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff); +#else + buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff); + buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff); + buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff); + buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff); +#endif + } while (0); + jump = jump->next; + } + + SLJIT_CACHE_FLUSH(code, code_ptr); + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_size = compiler->size * sizeof(sljit_ins); + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (((sljit_w)code_ptr) & 0x4) + code_ptr++; + sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_w)code, sljit_generate_code); + return code_ptr; +#else + return code; +#endif +} + +/* inp_flags: */ + +/* Creates an index in data_transfer_insts array. */ +#define WORD_DATA 0x00 +#define BYTE_DATA 0x01 +#define HALF_DATA 0x02 +#define INT_DATA 0x03 +#define SIGNED_DATA 0x04 +#define LOAD_DATA 0x08 +#define WRITE_BACK 0x10 +#define INDEXED 0x20 + +#define MEM_MASK 0x3f + +/* Other inp_flags. */ + +#define ARG_TEST 0x000100 +/* Integer opertion and set flags -> requires exts on 64 bit systems. */ +#define ALT_SIGN_EXT 0x000200 +/* This flag affects the RC() and OERC() macros. */ +#define ALT_SET_FLAGS 0x000400 +#define ALT_FORM1 0x010000 +#define ALT_FORM2 0x020000 +#define ALT_FORM3 0x040000 +#define ALT_FORM4 0x080000 +#define ALT_FORM5 0x100000 +#define ALT_FORM6 0x200000 + +/* Source and destination is register. */ +#define REG_DEST 0x000001 +#define REG1_SOURCE 0x000002 +#define REG2_SOURCE 0x000004 +/* getput_arg_fast returned true. */ +#define FAST_DEST 0x000008 +/* Multiple instructions are required. */ +#define SLOW_DEST 0x000010 +/* +ALT_SIGN_EXT 0x000200 +ALT_SET_FLAGS 0x000400 +ALT_FORM1 0x010000 +... +ALT_FORM6 0x200000 */ + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) +#include "sljitNativePPC_32.c" +#else +#include "sljitNativePPC_64.c" +#endif + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) +#define STACK_STORE STW +#define STACK_LOAD LWZ +#else +#define STACK_STORE STD +#define STACK_LOAD LD +#endif + +static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->has_locals = local_size > 0; + + FAIL_IF(push_inst(compiler, MFLR | D(0))); + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) )); + FAIL_IF(push_inst(compiler, STACK_STORE | S(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) )); + if (saveds >= 1) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) )); + if (saveds >= 2) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) )); + if (saveds >= 3) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) )); + if (saveds >= 4) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) )); + if (saveds >= 5) + FAIL_IF(push_inst(compiler, STACK_STORE | S(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) )); + FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w)) )); + + FAIL_IF(push_inst(compiler, ADDI | D(ZERO_REG) | A(0) | 0)); + if (args >= 1) + FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(SLJIT_SAVED_REG1) | B(SLJIT_TEMPORARY_REG1))); + if (args >= 2) + FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG2) | A(SLJIT_SAVED_REG2) | B(SLJIT_TEMPORARY_REG2))); + if (args >= 3) + FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG3) | A(SLJIT_SAVED_REG3) | B(SLJIT_TEMPORARY_REG3))); + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size; +#else + compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size; +#endif + compiler->local_size = (compiler->local_size + 15) & ~0xf; + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + if (compiler->local_size <= SIMM_MAX) + FAIL_IF(push_inst(compiler, STWU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size))); + else { + FAIL_IF(load_immediate(compiler, 0, -compiler->local_size)); + FAIL_IF(push_inst(compiler, STWUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0))); + } + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(2 * sizeof(sljit_w)))); +#else + if (compiler->local_size <= SIMM_MAX) + FAIL_IF(push_inst(compiler, STDU | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(-compiler->local_size))); + else { + FAIL_IF(load_immediate(compiler, 0, -compiler->local_size)); + FAIL_IF(push_inst(compiler, STDUX | S(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0))); + } + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM((7 + 8) * sizeof(sljit_w)))); +#endif + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + compiler->has_locals = local_size > 0; +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size; +#else + compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size; +#endif + compiler->local_size = (compiler->local_size + 15) & ~0xf; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + if (compiler->local_size <= SIMM_MAX) + FAIL_IF(push_inst(compiler, ADDI | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | IMM(compiler->local_size))); + else { + FAIL_IF(load_immediate(compiler, 0, compiler->local_size)); + FAIL_IF(push_inst(compiler, ADD | D(REAL_STACK_PTR) | A(REAL_STACK_PTR) | B(0))); + } + + FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(REAL_STACK_PTR) | IMM(sizeof(sljit_w)))); + if (compiler->saveds >= 5) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG2) | A(REAL_STACK_PTR) | IMM(-7 * (int)(sizeof(sljit_w))) )); + if (compiler->saveds >= 4) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_EREG1) | A(REAL_STACK_PTR) | IMM(-6 * (int)(sizeof(sljit_w))) )); + if (compiler->saveds >= 3) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG3) | A(REAL_STACK_PTR) | IMM(-5 * (int)(sizeof(sljit_w))) )); + if (compiler->saveds >= 2) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG2) | A(REAL_STACK_PTR) | IMM(-4 * (int)(sizeof(sljit_w))) )); + if (compiler->saveds >= 1) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_SAVED_REG1) | A(REAL_STACK_PTR) | IMM(-3 * (int)(sizeof(sljit_w))) )); + FAIL_IF(push_inst(compiler, STACK_LOAD | D(ZERO_REG) | A(REAL_STACK_PTR) | IMM(-2 * (int)(sizeof(sljit_w))) )); + if (compiler->has_locals) + FAIL_IF(push_inst(compiler, STACK_LOAD | D(SLJIT_LOCALS_REG) | A(REAL_STACK_PTR) | IMM(-(int)(sizeof(sljit_w))) )); + + FAIL_IF(push_inst(compiler, MTLR | S(0))); + FAIL_IF(push_inst(compiler, BLR)); + + return SLJIT_SUCCESS; +} + +#undef STACK_STORE +#undef STACK_LOAD + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +/* i/x - immediate/indexed form + n/w - no write-back / write-back (1 bit) + s/l - store/load (1 bit) + u/s - signed/unsigned (1 bit) + w/b/h/i - word/byte/half/int allowed (2 bit) + It contans 32 items, but not all are different. */ + +/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */ +#define ADDR_MODE2 0x10000 +/* 64-bit only: there is no lwau instruction. */ +#define UPDATE_REQ 0x20000 + +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) +#define ARCH_DEPEND(a, b) a +#define GET_INST_CODE(inst) (inst) +#else +#define ARCH_DEPEND(a, b) b +#define GET_INST_CODE(index) ((inst) & ~(ADDR_MODE2 | UPDATE_REQ)) +#endif + +static SLJIT_CONST sljit_ins data_transfer_insts[64] = { + +/* No write-back. */ + +/* i n s u w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */), +/* i n s u b */ HI(38) /* stb */, +/* i n s u h */ HI(44) /* sth*/, +/* i n s u i */ HI(36) /* stw */, + +/* i n s s w */ ARCH_DEPEND(HI(36) /* stw */, HI(62) | ADDR_MODE2 | 0x0 /* std */), +/* i n s s b */ HI(38) /* stb */, +/* i n s s h */ HI(44) /* sth*/, +/* i n s s i */ HI(36) /* stw */, + +/* i n l u w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */), +/* i n l u b */ HI(34) /* lbz */, +/* i n l u h */ HI(40) /* lhz */, +/* i n l u i */ HI(32) /* lwz */, + +/* i n l s w */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x0 /* ld */), +/* i n l s b */ HI(34) /* lbz */ /* EXTS_REQ */, +/* i n l s h */ HI(42) /* lha */, +/* i n l s i */ ARCH_DEPEND(HI(32) /* lwz */, HI(58) | ADDR_MODE2 | 0x2 /* lwa */), + +/* Write-back. */ + +/* i w s u w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */), +/* i w s u b */ HI(39) /* stbu */, +/* i w s u h */ HI(45) /* sthu */, +/* i w s u i */ HI(37) /* stwu */, + +/* i w s s w */ ARCH_DEPEND(HI(37) /* stwu */, HI(62) | ADDR_MODE2 | 0x1 /* stdu */), +/* i w s s b */ HI(39) /* stbu */, +/* i w s s h */ HI(45) /* sthu */, +/* i w s s i */ HI(37) /* stwu */, + +/* i w l u w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */), +/* i w l u b */ HI(35) /* lbzu */, +/* i w l u h */ HI(41) /* lhzu */, +/* i w l u i */ HI(33) /* lwzu */, + +/* i w l s w */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | 0x1 /* ldu */), +/* i w l s b */ HI(35) /* lbzu */ /* EXTS_REQ */, +/* i w l s h */ HI(43) /* lhau */, +/* i w l s i */ ARCH_DEPEND(HI(33) /* lwzu */, HI(58) | ADDR_MODE2 | UPDATE_REQ | 0x2 /* lwa */), + +/* ---------- */ +/* Indexed */ +/* ---------- */ + +/* No write-back. */ + +/* x n s u w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), +/* x n s u b */ HI(31) | LO(215) /* stbx */, +/* x n s u h */ HI(31) | LO(407) /* sthx */, +/* x n s u i */ HI(31) | LO(151) /* stwx */, + +/* x n s s w */ ARCH_DEPEND(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */), +/* x n s s b */ HI(31) | LO(215) /* stbx */, +/* x n s s h */ HI(31) | LO(407) /* sthx */, +/* x n s s i */ HI(31) | LO(151) /* stwx */, + +/* x n l u w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), +/* x n l u b */ HI(31) | LO(87) /* lbzx */, +/* x n l u h */ HI(31) | LO(279) /* lhzx */, +/* x n l u i */ HI(31) | LO(23) /* lwzx */, + +/* x n l s w */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */), +/* x n l s b */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */, +/* x n l s h */ HI(31) | LO(343) /* lhax */, +/* x n l s i */ ARCH_DEPEND(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */), + +/* Write-back. */ + +/* x w s u w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), +/* x w s u b */ HI(31) | LO(247) /* stbux */, +/* x w s u h */ HI(31) | LO(439) /* sthux */, +/* x w s u i */ HI(31) | LO(183) /* stwux */, + +/* x w s s w */ ARCH_DEPEND(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */), +/* x w s s b */ HI(31) | LO(247) /* stbux */, +/* x w s s h */ HI(31) | LO(439) /* sthux */, +/* x w s s i */ HI(31) | LO(183) /* stwux */, + +/* x w l u w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), +/* x w l u b */ HI(31) | LO(119) /* lbzux */, +/* x w l u h */ HI(31) | LO(311) /* lhzux */, +/* x w l u i */ HI(31) | LO(55) /* lwzux */, + +/* x w l s w */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */), +/* x w l s b */ HI(31) | LO(119) /* lbzux */ /* EXTS_REQ */, +/* x w l s h */ HI(31) | LO(375) /* lhaux */, +/* x w l s i */ ARCH_DEPEND(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */) + +}; + +#undef ARCH_DEPEND + +/* Simple cases, (no caching is required). */ +static int getput_arg_fast(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw) +{ + sljit_ins inst; +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + int tmp_reg; +#endif + + SLJIT_ASSERT(arg & SLJIT_MEM); + if (!(arg & 0xf)) { +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + if (argw <= SIMM_MAX && argw >= SIMM_MIN) { + if (inp_flags & ARG_TEST) + return 1; + + inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw)); + return -1; + } +#else + inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK]; + if (argw <= SIMM_MAX && argw >= SIMM_MIN && + (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) { + if (inp_flags & ARG_TEST) + return 1; + + push_inst(compiler, GET_INST_CODE(inst) | D(reg) | IMM(argw)); + return -1; + } +#endif + return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0; + } + + if (!(arg & 0xf0)) { +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + if (argw <= SIMM_MAX && argw >= SIMM_MIN) { + if (inp_flags & ARG_TEST) + return 1; + + inst = data_transfer_insts[inp_flags & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw)); + return -1; + } +#else + inst = data_transfer_insts[inp_flags & MEM_MASK]; + if (argw <= SIMM_MAX && argw >= SIMM_MIN && (!(inst & ADDR_MODE2) || (argw & 0x3) == 0)) { + if (inp_flags & ARG_TEST) + return 1; + + if ((inp_flags & WRITE_BACK) && (inst & UPDATE_REQ)) { + tmp_reg = (inp_flags & LOAD_DATA) ? (arg & 0xf) : TMP_REG3; + if (push_inst(compiler, ADDI | D(tmp_reg) | A(arg & 0xf) | IMM(argw))) + return -1; + arg = tmp_reg | SLJIT_MEM; + argw = 0; + } + push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | IMM(argw)); + return -1; + } +#endif + } + else if (!(argw & 0x3)) { + if (inp_flags & ARG_TEST) + return 1; + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B((arg >> 4) & 0xf)); + return -1; + } + return (inp_flags & ARG_TEST) ? SLJIT_SUCCESS : 0; +} + +/* See getput_arg below. + Note: can_cache is called only for binary operators. Those operator always + uses word arguments without write back. */ +static int can_cache(int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + SLJIT_ASSERT(arg & SLJIT_MEM); + SLJIT_ASSERT(next_arg & SLJIT_MEM); + + if (!(arg & 0xf)) { + if ((next_arg & SLJIT_MEM) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) + return 1; + return 0; + } + + if (arg & 0xf0) + return 0; + + if (argw <= SIMM_MAX && argw >= SIMM_MIN) { + if (arg == next_arg && (next_argw >= SIMM_MAX && next_argw <= SIMM_MIN)) + return 1; + } + + if (arg == next_arg && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) + return 1; + + return 0; +} + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define ADJUST_CACHED_IMM(imm) \ + if ((inst & ADDR_MODE2) && (imm & 0x3)) { \ + /* Adjust cached value. Fortunately this is really a rare case */ \ + compiler->cache_argw += imm & 0x3; \ + FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG3) | A(TMP_REG3) | (imm & 0x3))); \ + imm &= ~0x3; \ + } +#else +#define ADJUST_CACHED_IMM(imm) +#endif + +/* Emit the necessary instructions. See can_cache above. */ +static int getput_arg(struct sljit_compiler *compiler, int inp_flags, int reg, int arg, sljit_w argw, int next_arg, sljit_w next_argw) +{ + int tmp_r; + sljit_ins inst; + + SLJIT_ASSERT(arg & SLJIT_MEM); + + tmp_r = (inp_flags & LOAD_DATA) ? reg : TMP_REG3; + if ((arg & 0xf) == tmp_r) { + /* Special case for "mov reg, [reg, ... ]". + Caching would not happen anyway. */ + tmp_r = TMP_REG3; + compiler->cache_arg = 0; + compiler->cache_argw = 0; + } + + if (!(arg & 0xf)) { + inst = data_transfer_insts[(inp_flags & ~WRITE_BACK) & MEM_MASK]; + if ((compiler->cache_arg & SLJIT_IMM) && (((sljit_uw)argw - (sljit_uw)compiler->cache_argw) <= SIMM_MAX || ((sljit_uw)compiler->cache_argw - (sljit_uw)argw) <= SIMM_MAX)) { + argw = argw - compiler->cache_argw; + ADJUST_CACHED_IMM(argw); + SLJIT_ASSERT(!(inst & UPDATE_REQ)); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw)); + } + + if ((next_arg & SLJIT_MEM) && (argw - next_argw <= SIMM_MAX || next_argw - argw <= SIMM_MAX)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + + compiler->cache_arg = SLJIT_IMM; + compiler->cache_argw = argw; + tmp_r = TMP_REG3; + } + + FAIL_IF(load_immediate(compiler, tmp_r, argw)); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(tmp_r)); + } + + if (SLJIT_UNLIKELY(arg & 0xf0)) { + argw &= 0x3; + /* Otherwise getput_arg_fast would capture it. */ + SLJIT_ASSERT(argw); +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(tmp_r) | (argw << 11) | ((31 - argw) << 1))); +#else + FAIL_IF(push_inst(compiler, RLDI(tmp_r, (arg >> 4) & 0xf, argw, 63 - argw, 1))); +#endif + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r)); + } + + inst = data_transfer_insts[inp_flags & MEM_MASK]; + + if (compiler->cache_arg == arg && ((sljit_uw)argw - (sljit_uw)compiler->cache_argw <= SIMM_MAX || (sljit_uw)compiler->cache_argw - (sljit_uw)argw <= SIMM_MAX)) { + SLJIT_ASSERT(!(inp_flags & WRITE_BACK)); + argw = argw - compiler->cache_argw; + ADJUST_CACHED_IMM(argw); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3) | IMM(argw)); + } + + if ((compiler->cache_arg & SLJIT_IMM) && compiler->cache_argw == argw) { + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3)); + } + + if (argw == next_argw && (next_arg & SLJIT_MEM)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + + compiler->cache_arg = SLJIT_IMM; + compiler->cache_argw = argw; + + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(TMP_REG3)); + } + + if (arg == next_arg && !(inp_flags & WRITE_BACK) && ((sljit_uw)argw - (sljit_uw)next_argw <= SIMM_MAX || (sljit_uw)next_argw - (sljit_uw)argw <= SIMM_MAX)) { + SLJIT_ASSERT(inp_flags & LOAD_DATA); + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + FAIL_IF(push_inst(compiler, ADD | D(TMP_REG3) | A(TMP_REG3) | B(arg & 0xf))); + + compiler->cache_arg = arg; + compiler->cache_argw = argw; + + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(TMP_REG3)); + } + + /* Get the indexed version instead of the normal one. */ + inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK]; + SLJIT_ASSERT(!(inst & (ADDR_MODE2 | UPDATE_REQ))); + FAIL_IF(load_immediate(compiler, tmp_r, argw)); + return push_inst(compiler, GET_INST_CODE(inst) | D(reg) | A(arg & 0xf) | B(tmp_r)); +} + +static int emit_op(struct sljit_compiler *compiler, int op, int inp_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* arg1 goes to TMP_REG1 or src reg + arg2 goes to TMP_REG2, imm or src reg + TMP_REG3 can be used for caching + result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ + int dst_r; + int src1_r; + int src2_r; + int sugg_src2_r = TMP_REG2; + int flags = inp_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_FORM6 | ALT_SIGN_EXT | ALT_SET_FLAGS); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + /* Destination check. */ + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= ZERO_REG) { + dst_r = dst; + flags |= REG_DEST; + if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) + sugg_src2_r = dst_r; + } + else if (dst == SLJIT_UNUSED) { + if (op >= SLJIT_MOV && op <= SLJIT_MOVU_SI && !(src2 & SLJIT_MEM)) + return SLJIT_SUCCESS; + dst_r = TMP_REG2; + } + else { + SLJIT_ASSERT(dst & SLJIT_MEM); + if (getput_arg_fast(compiler, inp_flags | ARG_TEST, TMP_REG2, dst, dstw)) { + flags |= FAST_DEST; + dst_r = TMP_REG2; + } + else { + flags |= SLOW_DEST; + dst_r = 0; + } + } + + /* Source 1. */ + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= ZERO_REG) { + src1_r = src1; + flags |= REG1_SOURCE; + } + else if (src1 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if ((inp_flags & 0x3) == INT_DATA) { + if (inp_flags & SIGNED_DATA) + src1w = (signed int)src1w; + else + src1w = (unsigned int)src1w; + } +#endif + FAIL_IF(load_immediate(compiler, TMP_REG1, src1w)); + src1_r = TMP_REG1; + } + else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w)) { + FAIL_IF(compiler->error); + src1_r = TMP_REG1; + } + else + src1_r = 0; + + /* Source 2. */ + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= ZERO_REG) { + src2_r = src2; + flags |= REG2_SOURCE; + if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_SI) + dst_r = src2_r; + } + else if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if ((inp_flags & 0x3) == INT_DATA) { + if (inp_flags & SIGNED_DATA) + src2w = (signed int)src2w; + else + src2w = (unsigned int)src2w; + } +#endif + FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w)); + src2_r = sugg_src2_r; + } + else if (getput_arg_fast(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w)) { + FAIL_IF(compiler->error); + src2_r = sugg_src2_r; + } + else + src2_r = 0; + + /* src1_r, src2_r and dst_r can be zero (=unprocessed). + All arguments are complex addressing modes, and it is a binary operator. */ + if (src1_r == 0 && src2_r == 0 && dst_r == 0) { + if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w)); + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + } + else { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG2, src2, src2w, dst, dstw)); + } + src1_r = TMP_REG1; + src2_r = TMP_REG2; + } + else if (src1_r == 0 && src2_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w)); + src1_r = TMP_REG1; + } + else if (src1_r == 0 && dst_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw)); + src1_r = TMP_REG1; + } + else if (src2_r == 0 && dst_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, dst, dstw)); + src2_r = sugg_src2_r; + } + + if (dst_r == 0) + dst_r = TMP_REG2; + + if (src1_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, 0, 0)); + src1_r = TMP_REG1; + } + + if (src2_r == 0) { + FAIL_IF(getput_arg(compiler, inp_flags | LOAD_DATA, sugg_src2_r, src2, src2w, 0, 0)); + src2_r = sugg_src2_r; + } + + FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); + + if (flags & (FAST_DEST | SLOW_DEST)) { + if (flags & FAST_DEST) + FAIL_IF(getput_arg_fast(compiler, inp_flags, dst_r, dst, dstw)); + else + FAIL_IF(getput_arg(compiler, inp_flags, dst_r, dst, dstw, 0, 0)); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + CHECK_ERROR(); + check_sljit_emit_op0(compiler, op); + + switch (GET_OPCODE(op)) { + case SLJIT_BREAKPOINT: + case SLJIT_NOP: + return push_inst(compiler, NOP); + break; + case SLJIT_UMUL: + case SLJIT_SMUL: + FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1))); +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHDU : MULHD) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)); +#else + FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, (GET_OPCODE(op) == SLJIT_UMUL ? MULHWU : MULHW) | D(SLJIT_TEMPORARY_REG2) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2)); +#endif + case SLJIT_UDIV: + case SLJIT_SDIV: + FAIL_IF(push_inst(compiler, OR | S(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG1))); +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op & SLJIT_INT_OP) { + FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2))); + FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1)); + } + FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVDU : DIVD) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2))); + FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1)); +#else + FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_UDIV ? DIVWU : DIVW) | D(SLJIT_TEMPORARY_REG1) | A(TMP_REG1) | B(SLJIT_TEMPORARY_REG2))); + FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG1) | B(SLJIT_TEMPORARY_REG2))); + return push_inst(compiler, SUBF | D(SLJIT_TEMPORARY_REG2) | A(SLJIT_TEMPORARY_REG2) | B(TMP_REG1)); +#endif + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0; + + CHECK_ERROR(); + check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + + if ((src & SLJIT_IMM) && srcw == 0) + src = ZERO_REG; + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op & SLJIT_INT_OP) { + inp_flags |= INT_DATA | SIGNED_DATA; + if (src & SLJIT_IMM) + srcw = (int)srcw; + } +#endif + if (op & SLJIT_SET_O) + FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG))); + + switch (GET_OPCODE(op)) { + case SLJIT_MOV: + return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_UI: + return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_SI: + return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOV_UB: + return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOV_SB: + return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOV_UH: + return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOV_SH: + return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_MOVU: + return emit_op(compiler, SLJIT_MOV, inp_flags | WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_UI: + return emit_op(compiler, SLJIT_MOV_UI, inp_flags | INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_SI: + return emit_op(compiler, SLJIT_MOV_SI, inp_flags | INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_MOVU_UB: + return emit_op(compiler, SLJIT_MOV_UB, inp_flags | BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw); + + case SLJIT_MOVU_SB: + return emit_op(compiler, SLJIT_MOV_SB, inp_flags | BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw); + + case SLJIT_MOVU_UH: + return emit_op(compiler, SLJIT_MOV_UH, inp_flags | HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw); + + case SLJIT_MOVU_SH: + return emit_op(compiler, SLJIT_MOV_SH, inp_flags | HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw); + + case SLJIT_NOT: + return emit_op(compiler, SLJIT_NOT, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_NEG: + return emit_op(compiler, SLJIT_NEG, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw); + + case SLJIT_CLZ: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + return emit_op(compiler, SLJIT_CLZ, inp_flags | (!(op & SLJIT_INT_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw); +#else + return emit_op(compiler, SLJIT_CLZ, inp_flags, dst, dstw, TMP_REG1, 0, src, srcw); +#endif + } + + return SLJIT_SUCCESS; +} + +#define TEST_SL_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN) + +#define TEST_UL_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && !((srcw) & ~0xffff)) + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define TEST_SH_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && !((srcw) & 0xffff) && (srcw) <= SLJIT_W(0x7fffffff) && (srcw) >= SLJIT_W(-0x80000000)) +#else +#define TEST_SH_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && !((srcw) & 0xffff)) +#endif + +#define TEST_UH_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000)) + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define TEST_ADD_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && (srcw) <= SLJIT_W(0x7fff7fff) && (srcw) >= SLJIT_W(-0x80000000)) +#else +#define TEST_ADD_IMM(src, srcw) \ + ((src) & SLJIT_IMM) +#endif + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) +#define TEST_UI_IMM(src, srcw) \ + (((src) & SLJIT_IMM) && !((srcw) & ~0xffffffff)) +#else +#define TEST_UI_IMM(src, srcw) \ + ((src) & SLJIT_IMM) +#endif + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int inp_flags = GET_FLAGS(op) ? ALT_SET_FLAGS : 0; + + CHECK_ERROR(); + check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + if ((src1 & SLJIT_IMM) && src1w == 0) + src1 = ZERO_REG; + if ((src2 & SLJIT_IMM) && src2w == 0) + src2 = ZERO_REG; + +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op & SLJIT_INT_OP) { + inp_flags |= INT_DATA | SIGNED_DATA; + if (src1 & SLJIT_IMM) + src1w = (src1w << 32) >> 32; + if (src2 & SLJIT_IMM) + src2w = (src2w << 32) >> 32; + if (GET_FLAGS(op)) + inp_flags |= ALT_SIGN_EXT; + } +#endif + if (op & SLJIT_SET_O) + FAIL_IF(push_inst(compiler, MTXER | S(ZERO_REG))); + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + } + if (TEST_SH_IMM(src2, src2w)) { + compiler->imm = (src2w >> 16) & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_SH_IMM(src1, src1w)) { + compiler->imm = (src1w >> 16) & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + } + /* Range between -1 and -32768 is covered above. */ + if (TEST_ADD_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_ADD_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + if (!(GET_FLAGS(op) & (SLJIT_SET_E | SLJIT_SET_O))) { + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + return emit_op(compiler, SLJIT_ADD, inp_flags, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_ADDC: + return emit_op(compiler, SLJIT_ADDC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SUB: + if (!GET_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) { + if (TEST_SL_IMM(src2, -src2w)) { + compiler->imm = (-src2w) & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + } + if (TEST_SH_IMM(src2, -src2w)) { + compiler->imm = ((-src2w) >> 16) & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + /* Range between -1 and -32768 is covered above. */ + if (TEST_ADD_IMM(src2, -src2w)) { + compiler->imm = -src2w & 0xffffffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0); + } + } + if (dst == SLJIT_UNUSED && (op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U)) && !(op & (SLJIT_SET_O | SLJIT_SET_C))) { + if (!(op & SLJIT_SET_U)) { + /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (GET_FLAGS(op) == SLJIT_SET_E && TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + if (!(op & (SLJIT_SET_E | SLJIT_SET_S))) { + /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ + if (TEST_UL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w); + } + if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= 0x7fff) { + compiler->imm = src2w; + return emit_op(compiler, SLJIT_SUB, inp_flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, SLJIT_SUB, inp_flags | ((op & SLJIT_SET_U) ? ALT_FORM4 : 0) | ((op & (SLJIT_SET_E | SLJIT_SET_S)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w); + } + if (!(op & (SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_O))) { + if (TEST_SL_IMM(src2, -src2w)) { + compiler->imm = (-src2w) & 0xffff; + return emit_op(compiler, SLJIT_ADD, inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + } + /* We know ALT_SIGN_EXT is set if it is an SLJIT_INT_OP on 64 bit systems. */ + return emit_op(compiler, SLJIT_SUB, inp_flags | (!(op & SLJIT_SET_U) ? 0 : ALT_FORM6), dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SUBC: + return emit_op(compiler, SLJIT_SUBC, inp_flags | (!(op & SLJIT_KEEP_FLAGS) ? 0 : ALT_FORM1), dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_MUL: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op & SLJIT_INT_OP) + inp_flags |= ALT_FORM2; +#endif + if (!GET_FLAGS(op)) { + if (TEST_SL_IMM(src2, src2w)) { + compiler->imm = src2w & 0xffff; + return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_SL_IMM(src1, src1w)) { + compiler->imm = src1w & 0xffff; + return emit_op(compiler, SLJIT_MUL, inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + return emit_op(compiler, SLJIT_MUL, inp_flags, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + /* Commutative unsigned operations. */ + if (!GET_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) { + if (TEST_UL_IMM(src2, src2w)) { + compiler->imm = src2w; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_UL_IMM(src1, src1w)) { + compiler->imm = src1w; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0); + } + if (TEST_UH_IMM(src2, src2w)) { + compiler->imm = (src2w >> 16) & 0xffff; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_UH_IMM(src1, src1w)) { + compiler->imm = (src1w >> 16) & 0xffff; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + if (!GET_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) { + if (TEST_UI_IMM(src2, src2w)) { + compiler->imm = src2w; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0); + } + if (TEST_UI_IMM(src1, src1w)) { + compiler->imm = src1w; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0); + } + } + return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w); + + case SLJIT_SHL: + case SLJIT_LSHR: + case SLJIT_ASHR: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + if (op & SLJIT_INT_OP) + inp_flags |= ALT_FORM2; +#endif + if (src2 & SLJIT_IMM) { + compiler->imm = src2w; + return emit_op(compiler, GET_OPCODE(op), inp_flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0); + } + return emit_op(compiler, GET_OPCODE(op), inp_flags, dst, dstw, src1, src1w, src2, src2w); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + check_sljit_get_register_index(reg); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + CHECK_ERROR(); + check_sljit_emit_op_custom(compiler, instruction, size); + SLJIT_ASSERT(size == 4); + + return push_inst(compiler, *(sljit_ins*)instruction); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + /* Always available. */ + return 1; +} + +static int emit_fpu_data_transfer(struct sljit_compiler *compiler, int fpu_reg, int load, int arg, sljit_w argw) +{ + SLJIT_ASSERT(arg & SLJIT_MEM); + + /* Fast loads and stores. */ + if (!(arg & 0xf0)) { + /* Both for (arg & 0xf) == SLJIT_UNUSED and (arg & 0xf) != SLJIT_UNUSED. */ + if (argw <= SIMM_MAX && argw >= SIMM_MIN) + return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(arg & 0xf) | IMM(argw)); + } + + if (arg & 0xf0) { + argw &= 0x3; + if (argw) { +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + FAIL_IF(push_inst(compiler, RLWINM | S((arg >> 4) & 0xf) | A(TMP_REG2) | (argw << 11) | ((31 - argw) << 1))); +#else + FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, (arg >> 4) & 0xf, argw, 63 - argw, 1))); +#endif + return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B(TMP_REG2)); + } + return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(arg & 0xf) | B((arg >> 4) & 0xf)); + } + + /* Use cache. */ + if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) + return push_inst(compiler, (load ? LFD : STFD) | FD(fpu_reg) | A(TMP_REG3) | IMM(argw - compiler->cache_argw)); + + /* Put value to cache. */ + compiler->cache_arg = arg; + compiler->cache_argw = argw; + + FAIL_IF(load_immediate(compiler, TMP_REG3, argw)); + if (!(arg & 0xf)) + return push_inst(compiler, (load ? LFDX : STFDX) | FD(fpu_reg) | A(0) | B(TMP_REG3)); + return push_inst(compiler, (load ? LFDUX : STFDUX) | FD(fpu_reg) | A(TMP_REG3) | B(arg & 0xf)); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int dst_fr; + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + if (GET_OPCODE(op) == SLJIT_FCMP) { + if (dst > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, dst, dstw)); + dst = TMP_FREG1; + } + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src, srcw)); + src = TMP_FREG2; + } + return push_inst(compiler, FCMPU | CRD(4) | FA(dst) | FB(src)); + } + + dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, dst_fr, 1, src, srcw)); + src = dst_fr; + } + + switch (op) { + case SLJIT_FMOV: + if (src != dst_fr && dst_fr != TMP_FREG1) + FAIL_IF(push_inst(compiler, FMR | FD(dst_fr) | FB(src))); + break; + case SLJIT_FNEG: + FAIL_IF(push_inst(compiler, FNEG | FD(dst_fr) | FB(src))); + break; + case SLJIT_FABS: + FAIL_IF(push_inst(compiler, FABS | FD(dst_fr) | FB(src))); + break; + } + + if (dst_fr == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, src, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_fr; + + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + + compiler->cache_arg = 0; + compiler->cache_argw = 0; + + dst_fr = (dst > SLJIT_FLOAT_REG4) ? TMP_FREG1 : dst; + + if (src2 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w)); + src2 = TMP_FREG2; + } + + if (src1 > SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w)); + src1 = TMP_FREG1; + } + + switch (op) { + case SLJIT_FADD: + FAIL_IF(push_inst(compiler, FADD | FD(dst_fr) | FA(src1) | FB(src2))); + break; + + case SLJIT_FSUB: + FAIL_IF(push_inst(compiler, FSUB | FD(dst_fr) | FA(src1) | FB(src2))); + break; + + case SLJIT_FMUL: + FAIL_IF(push_inst(compiler, FMUL | FD(dst_fr) | FA(src1) | FC(src2) /* FMUL use FC as src2 */)); + break; + + case SLJIT_FDIV: + FAIL_IF(push_inst(compiler, FDIV | FD(dst_fr) | FA(src1) | FB(src2))); + break; + } + + if (dst_fr == TMP_FREG1) + FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 0, dst, dstw)); + + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + + compiler->has_locals = local_size > 0; +#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) + compiler->local_size = (2 + saveds + 2) * sizeof(sljit_w) + local_size; +#else + compiler->local_size = (2 + saveds + 7 + 8) * sizeof(sljit_w) + local_size; +#endif + compiler->local_size = (compiler->local_size + 15) & ~0xf; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return push_inst(compiler, MFLR | D(dst)); + else if (dst & SLJIT_MEM) { + FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG2))); + return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + FAIL_IF(push_inst(compiler, MTLR | S(src))); + else { + if (src & SLJIT_MEM) + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + else if (src & SLJIT_IMM) + FAIL_IF(load_immediate(compiler, TMP_REG2, srcw)); + FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); + } + return push_inst(compiler, BLR); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + check_sljit_emit_label(compiler); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, int type) +{ + switch (type) { + case SLJIT_C_EQUAL: + return (12 << 21) | (2 << 16); + + case SLJIT_C_NOT_EQUAL: + return (4 << 21) | (2 << 16); + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + return (12 << 21) | ((4 + 0) << 16); + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + return (4 << 21) | ((4 + 0) << 16); + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + return (12 << 21) | ((4 + 1) << 16); + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + return (4 << 21) | ((4 + 1) << 16); + + case SLJIT_C_SIG_LESS: + return (12 << 21) | (0 << 16); + + case SLJIT_C_SIG_GREATER_EQUAL: + return (4 << 21) | (0 << 16); + + case SLJIT_C_SIG_GREATER: + return (12 << 21) | (1 << 16); + + case SLJIT_C_SIG_LESS_EQUAL: + return (4 << 21) | (1 << 16); + + case SLJIT_C_OVERFLOW: + case SLJIT_C_MUL_OVERFLOW: + return (12 << 21) | (3 << 16); + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + return (4 << 21) | (3 << 16); + + case SLJIT_C_FLOAT_EQUAL: + return (12 << 21) | ((4 + 2) << 16); + + case SLJIT_C_FLOAT_NOT_EQUAL: + return (4 << 21) | ((4 + 2) << 16); + + case SLJIT_C_FLOAT_NAN: + return (12 << 21) | ((4 + 3) << 16); + + case SLJIT_C_FLOAT_NOT_NAN: + return (4 << 21) | ((4 + 3) << 16); + + default: + SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL3); + return (20 << 21); + } +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + struct sljit_jump *jump; + sljit_ins bo_bi_flags; + + CHECK_ERROR_PTR(); + check_sljit_emit_jump(compiler, type); + + bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff); + if (!bo_bi_flags) + return NULL; + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + /* In PPC, we don't need to touch the arguments. */ + if (type >= SLJIT_JUMP) + jump->flags |= UNCOND_B; + + PTR_FAIL_IF(emit_const(compiler, TMP_REG1, 0)); + PTR_FAIL_IF(push_inst(compiler, MTCTR | S(TMP_REG1))); + jump->addr = compiler->size; + PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0))); + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + sljit_ins bo_bi_flags; + struct sljit_jump *jump = NULL; + int src_r; + + CHECK_ERROR(); + check_sljit_emit_ijump(compiler, type, src, srcw); + + bo_bi_flags = get_bo_bi_flags(compiler, type); + FAIL_IF(!bo_bi_flags); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) + src_r = src; + else if (src & SLJIT_IMM) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF(!jump); + set_jump(jump, compiler, JUMP_ADDR | UNCOND_B); + jump->u.target = srcw; + + FAIL_IF(emit_const(compiler, TMP_REG2, 0)); + src_r = TMP_REG2; + } + else { + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + src_r = TMP_REG2; + } + + FAIL_IF(push_inst(compiler, MTCTR | S(src_r))); + if (jump) + jump->addr = compiler->size; + return push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)); +} + +/* Get a bit from CR, all other bits are zeroed. */ +#define GET_CR_BIT(bit, dst) \ + FAIL_IF(push_inst(compiler, MFCR | D(dst))); \ + FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | ((1 + (bit)) << 11) | (31 << 6) | (31 << 1))); + +#define INVERT_BIT(dst) \ + FAIL_IF(push_inst(compiler, XORI | S(dst) | A(dst) | 0x1)); + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + int reg; + + CHECK_ERROR(); + check_sljit_emit_cond_value(compiler, op, dst, dstw, type); + + if (dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + + switch (type) { + case SLJIT_C_EQUAL: + GET_CR_BIT(2, reg); + break; + + case SLJIT_C_NOT_EQUAL: + GET_CR_BIT(2, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + GET_CR_BIT(4 + 0, reg); + break; + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + GET_CR_BIT(4 + 0, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + GET_CR_BIT(4 + 1, reg); + break; + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + GET_CR_BIT(4 + 1, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_SIG_LESS: + GET_CR_BIT(0, reg); + break; + + case SLJIT_C_SIG_GREATER_EQUAL: + GET_CR_BIT(0, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_SIG_GREATER: + GET_CR_BIT(1, reg); + break; + + case SLJIT_C_SIG_LESS_EQUAL: + GET_CR_BIT(1, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_OVERFLOW: + case SLJIT_C_MUL_OVERFLOW: + GET_CR_BIT(3, reg); + break; + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + GET_CR_BIT(3, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_FLOAT_EQUAL: + GET_CR_BIT(4 + 2, reg); + break; + + case SLJIT_C_FLOAT_NOT_EQUAL: + GET_CR_BIT(4 + 2, reg); + INVERT_BIT(reg); + break; + + case SLJIT_C_FLOAT_NAN: + GET_CR_BIT(4 + 3, reg); + break; + + case SLJIT_C_FLOAT_NOT_NAN: + GET_CR_BIT(4 + 3, reg); + INVERT_BIT(reg); + break; + + default: + SLJIT_ASSERT_STOP(); + break; + } + + if (GET_OPCODE(op) == SLJIT_OR) + return emit_op(compiler, GET_OPCODE(op), GET_FLAGS(op) ? ALT_SET_FLAGS : 0, dst, dstw, dst, dstw, TMP_REG2, 0); + + if (reg == TMP_REG2) + return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + struct sljit_const *const_; + int reg; + + CHECK_ERROR_PTR(); + check_sljit_emit_const(compiler, dst, dstw, init_value); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REG2; + + PTR_FAIL_IF(emit_const(compiler, reg, init_value)); + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); + return const_; +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_32.c b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c new file mode 100644 index 0000000000..68bca8441a --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_32.c @@ -0,0 +1,517 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* x86 32-bit arch dependent functions. */ + +static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm) +{ + sljit_ub *buf; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_w)); + FAIL_IF(!buf); + INC_SIZE(1 + sizeof(sljit_w)); + *buf++ = opcode; + *(sljit_w*)buf = imm; + return SLJIT_SUCCESS; +} + +static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type) +{ + if (type == SLJIT_JUMP) { + *code_ptr++ = 0xe9; + jump->addr++; + } + else if (type >= SLJIT_FAST_CALL) { + *code_ptr++ = 0xe8; + jump->addr++; + } + else { + *code_ptr++ = 0x0f; + *code_ptr++ = get_jump_code(type); + jump->addr += 2; + } + + if (jump->flags & JUMP_LABEL) + jump->flags |= PATCH_MW; + else + *(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4); + code_ptr += 4; + + return code_ptr; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size; + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->args = args; + compiler->flags_saved = 0; + +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0); +#else + size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0); +#endif + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + + INC_SIZE(size); + PUSH_REG(reg_map[TMP_REGISTER]); +#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (args > 0) { + *buf++ = 0x8b; + *buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3); + } +#endif + if (saveds > 2) + PUSH_REG(reg_map[SLJIT_SAVED_REG3]); + if (saveds > 1) + PUSH_REG(reg_map[SLJIT_SAVED_REG2]); + if (saveds > 0) + PUSH_REG(reg_map[SLJIT_SAVED_REG1]); + +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (args > 0) { + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3]; + } + if (args > 1) { + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2]; + } + if (args > 2) { + *buf++ = 0x8b; + *buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3); + *buf++ = 0x24; + *buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */ + } +#else + if (args > 0) { + *buf++ = 0x8b; + *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER]; + *buf++ = sizeof(sljit_w) * 2; + } + if (args > 1) { + *buf++ = 0x8b; + *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER]; + *buf++ = sizeof(sljit_w) * 3; + } + if (args > 2) { + *buf++ = 0x8b; + *buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER]; + *buf++ = sizeof(sljit_w) * 4; + } +#endif + + local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); + compiler->temporaries_start = local_size; + if (temporaries > 3) + local_size += (temporaries - 3) * sizeof(sljit_uw); + compiler->saveds_start = local_size; + if (saveds > 3) + local_size += (saveds - 3) * sizeof(sljit_uw); + +#ifdef _WIN32 + if (local_size > 1024) { + FAIL_IF(emit_do_imm(compiler, 0xb8 + reg_map[SLJIT_TEMPORARY_REG1], local_size)); + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack))); + } +#endif + + compiler->local_size = local_size; + if (local_size > 0) + return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d, + SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->args = args; + compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); + compiler->temporaries_start = compiler->local_size; + if (temporaries > 3) + compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); + compiler->saveds_start = compiler->local_size; + if (saveds > 3) + compiler->local_size += (saveds - 3) * sizeof(sljit_uw); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + int size; + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + SLJIT_ASSERT(compiler->args >= 0); + + compiler->flags_saved = 0; + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + if (compiler->local_size > 0) + FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05, + SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size)); + + size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3); +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (compiler->args > 2) + size += 2; +#else + if (compiler->args > 0) + size += 2; +#endif + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + + INC_SIZE(size); + + if (compiler->saveds > 0) + POP_REG(reg_map[SLJIT_SAVED_REG1]); + if (compiler->saveds > 1) + POP_REG(reg_map[SLJIT_SAVED_REG2]); + if (compiler->saveds > 2) + POP_REG(reg_map[SLJIT_SAVED_REG3]); + POP_REG(reg_map[TMP_REGISTER]); +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (compiler->args > 2) + RETN(sizeof(sljit_w)); + else + RET(); +#else + if (compiler->args > 0) + RETN(compiler->args * sizeof(sljit_w)); + else + RET(); +#endif + + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +/* Size contains the flags as well. */ +static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size, + /* The register or immediate operand. */ + int a, sljit_w imma, + /* The general operand (not immediate). */ + int b, sljit_w immb) +{ + sljit_ub *buf; + sljit_ub *buf_ptr; + int flags = size & ~0xf; + int inst_size; + + /* Both cannot be switched on. */ + SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); + /* Size flags not allowed for typed instructions. */ + SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); + /* Both size flags cannot be switched on. */ + SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + /* SSE2 and immediate is not possible. */ + SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); +#endif + + size &= 0xf; + inst_size = size; + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + if (flags & EX86_PREF_F2) + inst_size++; +#endif + if (flags & EX86_PREF_66) + inst_size++; + + /* Calculate size of b. */ + inst_size += 1; /* mod r/m byte. */ + if (b & SLJIT_MEM) { + if ((b & 0x0f) == SLJIT_UNUSED) + inst_size += sizeof(sljit_w); + else if (immb != 0 && !(b & 0xf0)) { + /* Immediate operand. */ + if (immb <= 127 && immb >= -128) + inst_size += sizeof(sljit_b); + else + inst_size += sizeof(sljit_w); + } + + if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0)) + b |= SLJIT_LOCALS_REG << 4; + + if ((b & 0xf0) != SLJIT_UNUSED) + inst_size += 1; /* SIB byte. */ + } + + /* Calculate size of a. */ + if (a & SLJIT_IMM) { + if (flags & EX86_BIN_INS) { + if (imma <= 127 && imma >= -128) { + inst_size += 1; + flags |= EX86_BYTE_ARG; + } else + inst_size += 4; + } + else if (flags & EX86_SHIFT_INS) { + imma &= 0x1f; + if (imma != 1) { + inst_size ++; + flags |= EX86_BYTE_ARG; + } + } else if (flags & EX86_BYTE_ARG) + inst_size++; + else if (flags & EX86_HALF_ARG) + inst_size += sizeof(short); + else + inst_size += sizeof(sljit_w); + } + else + SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size); + PTR_FAIL_IF(!buf); + + /* Encoding the byte. */ + INC_SIZE(inst_size); +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + if (flags & EX86_PREF_F2) + *buf++ = 0xf2; +#endif + if (flags & EX86_PREF_66) + *buf++ = 0x66; + + buf_ptr = buf + size; + + /* Encode mod/rm byte. */ + if (!(flags & EX86_SHIFT_INS)) { + if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) + *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81; + + if ((a & SLJIT_IMM) || (a == 0)) + *buf_ptr = 0; +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + else if (!(flags & EX86_SSE2)) + *buf_ptr = reg_map[a] << 3; + else + *buf_ptr = a << 3; +#else + else + *buf_ptr = reg_map[a] << 3; +#endif + } + else { + if (a & SLJIT_IMM) { + if (imma == 1) + *buf = 0xd1; + else + *buf = 0xc1; + } else + *buf = 0xd3; + *buf_ptr = 0; + } + + if (!(b & SLJIT_MEM)) +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b); +#else + *buf_ptr++ |= 0xc0 + reg_map[b]; +#endif + else if ((b & 0x0f) != SLJIT_UNUSED) { + if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) { + if (immb != 0) { + if (immb <= 127 && immb >= -128) + *buf_ptr |= 0x40; + else + *buf_ptr |= 0x80; + } + + if ((b & 0xf0) == SLJIT_UNUSED) + *buf_ptr++ |= reg_map[b & 0x0f]; + else { + *buf_ptr++ |= 0x04; + *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3); + } + + if (immb != 0) { + if (immb <= 127 && immb >= -128) + *buf_ptr++ = immb; /* 8 bit displacement. */ + else { + *(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */ + buf_ptr += sizeof(sljit_w); + } + } + } + else { + *buf_ptr++ |= 0x04; + *buf_ptr++ = reg_map[b & 0x0f] | (reg_map[(b >> 4) & 0x0f] << 3) | (immb << 6); + } + } + else { + *buf_ptr++ |= 0x05; + *(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */ + buf_ptr += sizeof(sljit_w); + } + + if (a & SLJIT_IMM) { + if (flags & EX86_BYTE_ARG) + *buf_ptr = imma; + else if (flags & EX86_HALF_ARG) + *(short*)buf_ptr = imma; + else if (!(flags & EX86_SHIFT_INS)) + *(sljit_w*)buf_ptr = imma; + } + + return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1); +} + +/* --------------------------------------------------------------------- */ +/* Call / return instructions */ +/* --------------------------------------------------------------------- */ + +static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type) +{ + sljit_ub *buf; + +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + buf = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2); + FAIL_IF(!buf); + INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2); + + if (type >= SLJIT_CALL3) + PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]); + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_TEMPORARY_REG3] << 3) | reg_map[SLJIT_TEMPORARY_REG1]; +#else + buf = (sljit_ub*)ensure_buf(compiler, type - SLJIT_CALL0 + 1); + FAIL_IF(!buf); + INC_SIZE(type - SLJIT_CALL0); + if (type >= SLJIT_CALL3) + PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]); + if (type >= SLJIT_CALL2) + PUSH_REG(reg_map[SLJIT_TEMPORARY_REG2]); + PUSH_REG(reg_map[SLJIT_TEMPORARY_REG1]); +#endif + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->args = args; + compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); + compiler->temporaries_start = compiler->local_size; + if (temporaries > 3) + compiler->local_size += (temporaries - 3) * sizeof(sljit_uw); + compiler->saveds_start = compiler->local_size; + if (saveds > 3) + compiler->local_size += (saveds - 3) * sizeof(sljit_uw); + + CHECK_EXTRA_REGS(dst, dstw, (void)0); + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + + INC_SIZE(1); + POP_REG(reg_map[dst]); + return SLJIT_SUCCESS; + } + else if (dst & SLJIT_MEM) { + buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + FAIL_IF(!buf); + *buf++ = 0x8f; + return SLJIT_SUCCESS; + } + + /* For UNUSED dst. Uncommon, but possible. */ + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + + INC_SIZE(1); + POP_REG(reg_map[TMP_REGISTER]); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + CHECK_EXTRA_REGS(src, srcw, (void)0); + + if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1); + FAIL_IF(!buf); + + INC_SIZE(1 + 1); + PUSH_REG(reg_map[src]); + } + else if (src & SLJIT_MEM) { + buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); + FAIL_IF(!buf); + *buf++ = 0xff; + *buf |= 6 << 3; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + } + else { + /* SLJIT_IMM. */ + buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1); + FAIL_IF(!buf); + + INC_SIZE(5 + 1); + *buf++ = 0x68; + *(sljit_w*)buf = srcw; + buf += sizeof(sljit_w); + } + + RET(); + return SLJIT_SUCCESS; +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_64.c b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c new file mode 100644 index 0000000000..40d875b841 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_64.c @@ -0,0 +1,842 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* x86 64-bit arch dependent functions. */ + +static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm) +{ + sljit_ub *buf; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w)); + FAIL_IF(!buf); + INC_SIZE(2 + sizeof(sljit_w)); + *buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B); + *buf++ = 0xb8 + (reg_map[reg] & 0x7); + *(sljit_w*)buf = imm; + return SLJIT_SUCCESS; +} + +static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type) +{ + if (type < SLJIT_JUMP) { + *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10; + *code_ptr++ = 10 + 3; + } + + SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first); + *code_ptr++ = REX_W | REX_B; + *code_ptr++ = 0xb8 + 1; + jump->addr = (sljit_uw)code_ptr; + + if (jump->flags & JUMP_LABEL) + jump->flags |= PATCH_MD; + else + *(sljit_w*)code_ptr = jump->u.target; + + code_ptr += sizeof(sljit_w); + *code_ptr++ = REX_B; + *code_ptr++ = 0xff; + *code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */; + + return code_ptr; +} + +static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type) +{ + sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw)); + + if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) { + *code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */; + *(sljit_w*)code_ptr = delta; + } + else { + SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second); + *code_ptr++ = REX_W | REX_B; + *code_ptr++ = 0xb8 + 1; + *(sljit_w*)code_ptr = addr; + code_ptr += sizeof(sljit_w); + *code_ptr++ = REX_B; + *code_ptr++ = 0xff; + *code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */; + } + + return code_ptr; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int size, pushed_size; + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->flags_saved = 0; + + size = saveds; + /* Including the return address saved by the call instruction. */ + pushed_size = (saveds + 1) * sizeof(sljit_w); +#ifndef _WIN64 + if (saveds >= 2) + size += saveds - 1; +#else + /* Saving the virtual stack pointer. */ + compiler->has_locals = local_size > 0; + if (local_size > 0) { + size += 2; + pushed_size += sizeof(sljit_w); + } + if (saveds >= 4) + size += saveds - 3; + if (temporaries >= 5) { + size += (5 - 4) * 2; + pushed_size += sizeof(sljit_w); + } +#endif + size += args * 3; + if (size > 0) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + + INC_SIZE(size); + if (saveds >= 5) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg); + *buf++ = REX_B; + PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]); + } + if (saveds >= 4) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg); + *buf++ = REX_B; + PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]); + } + if (saveds >= 3) { +#ifndef _WIN64 + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg); + *buf++ = REX_B; +#else + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg); +#endif + PUSH_REG(reg_lmap[SLJIT_SAVED_REG3]); + } + if (saveds >= 2) { +#ifndef _WIN64 + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg); + *buf++ = REX_B; +#else + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg); +#endif + PUSH_REG(reg_lmap[SLJIT_SAVED_REG2]); + } + if (saveds >= 1) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG1] < 8, saved_reg1_is_loreg); + PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]); + } +#ifdef _WIN64 + if (temporaries >= 5) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg); + *buf++ = REX_B; + PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]); + } + if (local_size > 0) { + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_LOCALS_REG] >= 8, locals_reg_is_hireg); + *buf++ = REX_B; + PUSH_REG(reg_lmap[SLJIT_LOCALS_REG]); + } +#endif + +#ifndef _WIN64 + if (args > 0) { + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7; + } + if (args > 1) { + *buf++ = REX_W | REX_R; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6; + } + if (args > 2) { + *buf++ = REX_W | REX_R; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2; + } +#else + if (args > 0) { + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1; + } + if (args > 1) { + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2; + } + if (args > 2) { + *buf++ = REX_W | REX_B; + *buf++ = 0x8b; + *buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0; + } +#endif + } + + local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size; +#ifdef _WIN64 + local_size += 4 * sizeof(sljit_w); + compiler->local_size = local_size; + if (local_size > 1024) { + /* Allocate the stack for the function itself. */ + buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!buf); + INC_SIZE(4); + *buf++ = REX_W; + *buf++ = 0x83; + *buf++ = 0xc0 | (5 << 3) | 4; + /* Pushed size must be divisible by 8. */ + SLJIT_ASSERT(!(pushed_size & 0x7)); + if (pushed_size & 0x8) { + *buf++ = 5 * sizeof(sljit_w); + local_size -= 5 * sizeof(sljit_w); + } else { + *buf++ = 4 * sizeof(sljit_w); + local_size -= 4 * sizeof(sljit_w); + } + FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size)); + FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_touch_stack))); + } +#else + compiler->local_size = local_size; + if (local_size > 0) { +#endif + /* In case of Win64, local_size is always > 4 * sizeof(sljit_w) */ + if (local_size <= 127) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!buf); + INC_SIZE(4); + *buf++ = REX_W; + *buf++ = 0x83; + *buf++ = 0xc0 | (5 << 3) | 4; + *buf++ = local_size; + } + else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 7); + FAIL_IF(!buf); + INC_SIZE(7); + *buf++ = REX_W; + *buf++ = 0x81; + *buf++ = 0xc0 | (5 << 3) | 4; + *(sljit_hw*)buf = local_size; + buf += sizeof(sljit_hw); + } +#ifndef _WIN64 + } +#endif + +#ifdef _WIN64 + if (compiler->has_locals) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); + FAIL_IF(!buf); + INC_SIZE(5); + *buf++ = REX_W | REX_R; + *buf++ = 0x8d; + *buf++ = 0x40 | (reg_lmap[SLJIT_LOCALS_REG] << 3) | 0x4; + *buf++ = 0x24; + *buf = 4 * sizeof(sljit_w); + } +#endif + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size) +{ + int pushed_size; + + CHECK_ERROR_VOID(); + check_sljit_set_context(compiler, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + /* Including the return address saved by the call instruction. */ + pushed_size = (saveds + 1) * sizeof(sljit_w); +#ifdef _WIN64 + compiler->has_locals = local_size > 0; + if (local_size > 0) + pushed_size += sizeof(sljit_w); + if (temporaries >= 5) + pushed_size += sizeof(sljit_w); +#endif + compiler->local_size = ((local_size + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size; +#ifdef _WIN64 + compiler->local_size += 4 * sizeof(sljit_w); +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw) +{ + int size; + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_return(compiler, op, src, srcw); + + compiler->flags_saved = 0; + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + if (compiler->local_size > 0) { + if (compiler->local_size <= 127) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!buf); + INC_SIZE(4); + *buf++ = REX_W; + *buf++ = 0x83; + *buf++ = 0xc0 | (0 << 3) | 4; + *buf = compiler->local_size; + } + else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 7); + FAIL_IF(!buf); + INC_SIZE(7); + *buf++ = REX_W; + *buf++ = 0x81; + *buf++ = 0xc0 | (0 << 3) | 4; + *(sljit_hw*)buf = compiler->local_size; + } + } + + size = 1 + compiler->saveds; +#ifndef _WIN64 + if (compiler->saveds >= 2) + size += compiler->saveds - 1; +#else + if (compiler->has_locals) + size += 2; + if (compiler->saveds >= 4) + size += compiler->saveds - 3; + if (compiler->temporaries >= 5) + size += (5 - 4) * 2; +#endif + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + + INC_SIZE(size); + +#ifdef _WIN64 + if (compiler->has_locals) { + *buf++ = REX_B; + POP_REG(reg_lmap[SLJIT_LOCALS_REG]); + } + if (compiler->temporaries >= 5) { + *buf++ = REX_B; + POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]); + } +#endif + if (compiler->saveds >= 1) + POP_REG(reg_map[SLJIT_SAVED_REG1]); + if (compiler->saveds >= 2) { +#ifndef _WIN64 + *buf++ = REX_B; +#endif + POP_REG(reg_lmap[SLJIT_SAVED_REG2]); + } + if (compiler->saveds >= 3) { +#ifndef _WIN64 + *buf++ = REX_B; +#endif + POP_REG(reg_lmap[SLJIT_SAVED_REG3]); + } + if (compiler->saveds >= 4) { + *buf++ = REX_B; + POP_REG(reg_lmap[SLJIT_SAVED_EREG1]); + } + if (compiler->saveds >= 5) { + *buf++ = REX_B; + POP_REG(reg_lmap[SLJIT_SAVED_EREG2]); + } + + RET(); + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm) +{ + sljit_ub *buf; + + if (rex != 0) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw)); + FAIL_IF(!buf); + INC_SIZE(2 + sizeof(sljit_hw)); + *buf++ = rex; + *buf++ = opcode; + *(sljit_hw*)buf = imm; + } + else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw)); + FAIL_IF(!buf); + INC_SIZE(1 + sizeof(sljit_hw)); + *buf++ = opcode; + *(sljit_hw*)buf = imm; + } + return SLJIT_SUCCESS; +} + +static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size, + /* The register or immediate operand. */ + int a, sljit_w imma, + /* The general operand (not immediate). */ + int b, sljit_w immb) +{ + sljit_ub *buf; + sljit_ub *buf_ptr; + sljit_ub rex = 0; + int flags = size & ~0xf; + int inst_size; + + /* The immediate operand must be 32 bit. */ + SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma)); + /* Both cannot be switched on. */ + SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS)); + /* Size flags not allowed for typed instructions. */ + SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0); + /* Both size flags cannot be switched on. */ + SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG)); +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + /* SSE2 and immediate is not possible. */ + SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2)); +#endif + + size &= 0xf; + inst_size = size; + + if ((b & SLJIT_MEM) && !(b & 0xf0) && NOT_HALFWORD(immb)) { + if (emit_load_imm64(compiler, TMP_REG3, immb)) + return NULL; + immb = 0; + if (b & 0xf) + b |= TMP_REG3 << 4; + else + b |= TMP_REG3; + } + + if (!compiler->mode32 && !(flags & EX86_NO_REXW)) + rex |= REX_W; + else if (flags & EX86_REX) + rex |= REX; + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + if (flags & EX86_PREF_F2) + inst_size++; +#endif + if (flags & EX86_PREF_66) + inst_size++; + + /* Calculate size of b. */ + inst_size += 1; /* mod r/m byte. */ + if (b & SLJIT_MEM) { + if ((b & 0x0f) == SLJIT_UNUSED) + inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */ + else { + if (reg_map[b & 0x0f] >= 8) + rex |= REX_B; + if (immb != 0 && !(b & 0xf0)) { + /* Immediate operand. */ + if (immb <= 127 && immb >= -128) + inst_size += sizeof(sljit_b); + else + inst_size += sizeof(sljit_hw); + } + } + +#ifndef _WIN64 + if ((b & 0xf) == SLJIT_LOCALS_REG && (b & 0xf0) == 0) + b |= SLJIT_LOCALS_REG << 4; +#endif + + if ((b & 0xf0) != SLJIT_UNUSED) { + inst_size += 1; /* SIB byte. */ + if (reg_map[(b >> 4) & 0x0f] >= 8) + rex |= REX_X; + } + } +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + else if (!(flags & EX86_SSE2) && reg_map[b] >= 8) + rex |= REX_B; +#else + else if (reg_map[b] >= 8) + rex |= REX_B; +#endif + + if (a & SLJIT_IMM) { + if (flags & EX86_BIN_INS) { + if (imma <= 127 && imma >= -128) { + inst_size += 1; + flags |= EX86_BYTE_ARG; + } else + inst_size += 4; + } + else if (flags & EX86_SHIFT_INS) { + imma &= compiler->mode32 ? 0x1f : 0x3f; + if (imma != 1) { + inst_size ++; + flags |= EX86_BYTE_ARG; + } + } else if (flags & EX86_BYTE_ARG) + inst_size++; + else if (flags & EX86_HALF_ARG) + inst_size += sizeof(short); + else + inst_size += sizeof(sljit_hw); + } + else { + SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG); + /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */ +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + if (!(flags & EX86_SSE2) && reg_map[a] >= 8) + rex |= REX_R; +#else + if (reg_map[a] >= 8) + rex |= REX_R; +#endif + } + + if (rex) + inst_size++; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size); + PTR_FAIL_IF(!buf); + + /* Encoding the byte. */ + INC_SIZE(inst_size); +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + if (flags & EX86_PREF_F2) + *buf++ = 0xf2; +#endif + if (flags & EX86_PREF_66) + *buf++ = 0x66; + if (rex) + *buf++ = rex; + buf_ptr = buf + size; + + /* Encode mod/rm byte. */ + if (!(flags & EX86_SHIFT_INS)) { + if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM)) + *buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81; + + if ((a & SLJIT_IMM) || (a == 0)) + *buf_ptr = 0; +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + else if (!(flags & EX86_SSE2)) + *buf_ptr = reg_lmap[a] << 3; + else + *buf_ptr = a << 3; +#else + else + *buf_ptr = reg_lmap[a] << 3; +#endif + } + else { + if (a & SLJIT_IMM) { + if (imma == 1) + *buf = 0xd1; + else + *buf = 0xc1; + } else + *buf = 0xd3; + *buf_ptr = 0; + } + + if (!(b & SLJIT_MEM)) +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + *buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b); +#else + *buf_ptr++ |= 0xc0 + reg_lmap[b]; +#endif + else if ((b & 0x0f) != SLJIT_UNUSED) { +#ifdef _WIN64 + SLJIT_ASSERT((b & 0xf0) != (SLJIT_LOCALS_REG << 4)); +#endif + if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) { + if (immb != 0) { + if (immb <= 127 && immb >= -128) + *buf_ptr |= 0x40; + else + *buf_ptr |= 0x80; + } + + if ((b & 0xf0) == SLJIT_UNUSED) + *buf_ptr++ |= reg_lmap[b & 0x0f]; + else { + *buf_ptr++ |= 0x04; + *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3); + } + + if (immb != 0) { + if (immb <= 127 && immb >= -128) + *buf_ptr++ = immb; /* 8 bit displacement. */ + else { + *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */ + buf_ptr += sizeof(sljit_hw); + } + } + } + else { + *buf_ptr++ |= 0x04; + *buf_ptr++ = reg_lmap[b & 0x0f] | (reg_lmap[(b >> 4) & 0x0f] << 3) | (immb << 6); + } + } + else { + *buf_ptr++ |= 0x04; + *buf_ptr++ = 0x25; + *(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */ + buf_ptr += sizeof(sljit_hw); + } + + if (a & SLJIT_IMM) { + if (flags & EX86_BYTE_ARG) + *buf_ptr = imma; + else if (flags & EX86_HALF_ARG) + *(short*)buf_ptr = imma; + else if (!(flags & EX86_SHIFT_INS)) + *(sljit_hw*)buf_ptr = imma; + } + + return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1); +} + +/* --------------------------------------------------------------------- */ +/* Call / return instructions */ +/* --------------------------------------------------------------------- */ + +static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type) +{ + sljit_ub *buf; + +#ifndef _WIN64 + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); + FAIL_IF(!buf); + INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); + if (type >= SLJIT_CALL3) { + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3]; + } + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1]; +#else + SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6)); + FAIL_IF(!buf); + INC_SIZE((type < SLJIT_CALL3) ? 3 : 6); + if (type >= SLJIT_CALL3) { + *buf++ = REX_W | REX_R; + *buf++ = 0x8b; + *buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3]; + } + *buf++ = REX_W; + *buf++ = 0x8b; + *buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1]; +#endif + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw, int args, int temporaries, int saveds, int local_size) +{ + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_fast_enter(compiler, dst, dstw, args, temporaries, saveds, local_size); + + compiler->temporaries = temporaries; + compiler->saveds = saveds; + compiler->local_size = (local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1); +#ifdef _WIN64 + compiler->local_size += 4 * sizeof(sljit_w); +#endif + + /* For UNUSED dst. Uncommon, but possible. */ + if (dst == SLJIT_UNUSED) + dst = TMP_REGISTER; + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) { + if (reg_map[dst] < 8) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + + INC_SIZE(1); + POP_REG(reg_lmap[dst]); + } + else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + + INC_SIZE(2); + *buf++ = REX_B; + POP_REG(reg_lmap[dst]); + } + } + else if (dst & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + /* REX_W is not necessary (src is not immediate). */ + compiler->mode32 = 1; +#endif + buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + FAIL_IF(!buf); + *buf++ = 0x8f; + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw) +{ + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_fast_return(compiler, src, srcw); + + CHECK_EXTRA_REGS(src, srcw, (void)0); + + if ((src & SLJIT_IMM) && NOT_HALFWORD(srcw)) { + FAIL_IF(emit_load_imm64(compiler, TMP_REGISTER, srcw)); + src = TMP_REGISTER; + } + + if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) { + if (reg_map[src] < 8) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1); + FAIL_IF(!buf); + + INC_SIZE(1 + 1); + PUSH_REG(reg_lmap[src]); + } + else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1); + FAIL_IF(!buf); + + INC_SIZE(2 + 1); + *buf++ = REX_B; + PUSH_REG(reg_lmap[src]); + } + } + else if (src & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + /* REX_W is not necessary (src is not immediate). */ + compiler->mode32 = 1; +#endif + buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); + FAIL_IF(!buf); + *buf++ = 0xff; + *buf |= 6 << 3; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + } + else { + SLJIT_ASSERT(IS_HALFWORD(srcw)); + /* SLJIT_IMM. */ + buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1); + FAIL_IF(!buf); + + INC_SIZE(5 + 1); + *buf++ = 0x68; + *(sljit_hw*)buf = srcw; + buf += sizeof(sljit_hw); + } + + RET(); + return SLJIT_SUCCESS; +} + + +/* --------------------------------------------------------------------- */ +/* Extend input */ +/* --------------------------------------------------------------------- */ + +static int emit_mov_int(struct sljit_compiler *compiler, int sign, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + int dst_r; + + compiler->mode32 = 0; + + if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) + return SLJIT_SUCCESS; /* Empty instruction. */ + + if (src & SLJIT_IMM) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + if (sign || ((sljit_uw)srcw <= 0x7fffffff)) { + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc7; + return SLJIT_SUCCESS; + } + return emit_load_imm64(compiler, dst, srcw); + } + compiler->mode32 = 1; + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc7; + compiler->mode32 = 0; + return SLJIT_SUCCESS; + } + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER; + + if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3)) + dst_r = src; + else { + if (sign) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw); + FAIL_IF(!code); + *code++ = 0x63; + } else { + compiler->mode32 = 1; + FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw)); + compiler->mode32 = 0; + } + } + + if (dst & SLJIT_MEM) { + compiler->mode32 = 1; + code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x89; + compiler->mode32 = 0; + } + + return SLJIT_SUCCESS; +} diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c new file mode 100644 index 0000000000..0a44163802 --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c @@ -0,0 +1,2858 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name() +{ + return "x86" SLJIT_CPUINFO; +} + +/* + 32b register indexes: + 0 - EAX + 1 - ECX + 2 - EDX + 3 - EBX + 4 - none + 5 - EBP + 6 - ESI + 7 - EDI +*/ + +/* + 64b register indexes: + 0 - RAX + 1 - RCX + 2 - RDX + 3 - RBX + 4 - none + 5 - RBP + 6 - RSI + 7 - RDI + 8 - R8 - From now on REX prefix is required + 9 - R9 + 10 - R10 + 11 - R11 + 12 - R12 + 13 - R13 + 14 - R14 + 15 - R15 +*/ + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + +/* Last register + 1. */ +#define TMP_REGISTER (SLJIT_NO_REGISTERS + 1) + +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 2] = { + 0, 0, 2, 1, 0, 0, 3, 6, 7, 0, 0, 4, 5 +}; + +#define CHECK_EXTRA_REGS(p, w, do) \ + if (p >= SLJIT_TEMPORARY_EREG1 && p <= SLJIT_TEMPORARY_EREG2) { \ + w = compiler->temporaries_start + (p - SLJIT_TEMPORARY_EREG1) * sizeof(sljit_w); \ + p = SLJIT_MEM1(SLJIT_LOCALS_REG); \ + do; \ + } \ + else if (p >= SLJIT_SAVED_EREG1 && p <= SLJIT_SAVED_EREG2) { \ + w = compiler->saveds_start + (p - SLJIT_SAVED_EREG1) * sizeof(sljit_w); \ + p = SLJIT_MEM1(SLJIT_LOCALS_REG); \ + do; \ + } + +#else /* SLJIT_CONFIG_X86_32 */ + +/* Last register + 1. */ +#define TMP_REGISTER (SLJIT_NO_REGISTERS + 1) +#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) +#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) + +/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present + Note: avoid to use r12 and r13 for memory addessing + therefore r12 is better for SAVED_EREG than SAVED_REG. */ +#ifndef _WIN64 +/* 1st passed in rdi, 2nd argument passed in rsi, 3rd in rdx. */ +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = { + 0, 0, 6, 1, 8, 11, 3, 15, 14, 13, 12, 4, 2, 7, 9 +}; +/* low-map. reg_map & 0x7. */ +static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { + 0, 0, 6, 1, 0, 3, 3, 7, 6, 5, 4, 4, 2, 7, 1 +}; +#else +/* 1st passed in rcx, 2nd argument passed in rdx, 3rd in r8. */ +static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 4] = { + 0, 0, 2, 1, 11, 13, 3, 6, 7, 14, 12, 15, 10, 8, 9 +}; +/* low-map. reg_map & 0x7. */ +static SLJIT_CONST sljit_ub reg_lmap[SLJIT_NO_REGISTERS + 4] = { + 0, 0, 2, 1, 3, 5, 3, 6, 7, 6, 4, 7, 2, 0, 1 +}; +#endif + +#define REX_W 0x48 +#define REX_R 0x44 +#define REX_X 0x42 +#define REX_B 0x41 +#define REX 0x40 + +typedef unsigned int sljit_uhw; +typedef int sljit_hw; + +#define IS_HALFWORD(x) ((x) <= 0x7fffffffll && (x) >= -0x80000000ll) +#define NOT_HALFWORD(x) ((x) > 0x7fffffffll || (x) < -0x80000000ll) + +#define CHECK_EXTRA_REGS(p, w, do) + +#endif /* SLJIT_CONFIG_X86_32 */ + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) +#define TMP_FREG (SLJIT_FLOAT_REG4 + 1) +#endif + +/* Size flags for emit_x86_instruction: */ +#define EX86_BIN_INS 0x0010 +#define EX86_SHIFT_INS 0x0020 +#define EX86_REX 0x0040 +#define EX86_NO_REXW 0x0080 +#define EX86_BYTE_ARG 0x0100 +#define EX86_HALF_ARG 0x0200 +#define EX86_PREF_66 0x0400 + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) +#define EX86_PREF_F2 0x0800 +#define EX86_SSE2 0x1000 +#endif + +#define INC_SIZE(s) (*buf++ = (s), compiler->size += (s)) +#define INC_CSIZE(s) (*code++ = (s), compiler->size += (s)) + +#define PUSH_REG(r) (*buf++ = (0x50 + (r))) +#define POP_REG(r) (*buf++ = (0x58 + (r))) +#define RET() (*buf++ = (0xc3)) +#define RETN(n) (*buf++ = (0xc2), *buf++ = n, *buf++ = 0) +/* r32, r/m32 */ +#define MOV_RM(mod, reg, rm) (*buf++ = (0x8b), *buf++ = (mod) << 6 | (reg) << 3 | (rm)) + +static sljit_ub get_jump_code(int type) +{ + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_FLOAT_EQUAL: + return 0x84; + + case SLJIT_C_NOT_EQUAL: + case SLJIT_C_FLOAT_NOT_EQUAL: + return 0x85; + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + return 0x82; + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + return 0x83; + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + return 0x87; + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + return 0x86; + + case SLJIT_C_SIG_LESS: + return 0x8c; + + case SLJIT_C_SIG_GREATER_EQUAL: + return 0x8d; + + case SLJIT_C_SIG_GREATER: + return 0x8f; + + case SLJIT_C_SIG_LESS_EQUAL: + return 0x8e; + + case SLJIT_C_OVERFLOW: + case SLJIT_C_MUL_OVERFLOW: + return 0x80; + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + return 0x81; + + case SLJIT_C_FLOAT_NAN: + return 0x8a; + + case SLJIT_C_FLOAT_NOT_NAN: + return 0x8b; + } + return 0; +} + +static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type); +#endif + +static sljit_ub* generate_near_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_ub *code, int type) +{ + int short_jump; + sljit_uw label_addr; + + if (jump->flags & JUMP_LABEL) + label_addr = (sljit_uw)(code + jump->u.label->size); + else + label_addr = jump->u.target; + short_jump = (sljit_w)(label_addr - (jump->addr + 2)) >= -128 && (sljit_w)(label_addr - (jump->addr + 2)) <= 127; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((sljit_w)(label_addr - (jump->addr + 1)) > 0x7fffffffll || (sljit_w)(label_addr - (jump->addr + 1)) < -0x80000000ll) + return generate_far_jump_code(jump, code_ptr, type); +#endif + + if (type == SLJIT_JUMP) { + if (short_jump) + *code_ptr++ = 0xeb; + else + *code_ptr++ = 0xe9; + jump->addr++; + } + else if (type >= SLJIT_FAST_CALL) { + short_jump = 0; + *code_ptr++ = 0xe8; + jump->addr++; + } + else if (short_jump) { + *code_ptr++ = get_jump_code(type) - 0x10; + jump->addr++; + } + else { + *code_ptr++ = 0x0f; + *code_ptr++ = get_jump_code(type); + jump->addr += 2; + } + + if (short_jump) { + jump->flags |= PATCH_MB; + code_ptr += sizeof(sljit_b); + } else { + jump->flags |= PATCH_MW; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + code_ptr += sizeof(sljit_w); +#else + code_ptr += sizeof(sljit_hw); +#endif + } + + return code_ptr; +} + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_memory_fragment *buf; + sljit_ub *code; + sljit_ub *code_ptr; + sljit_ub *buf_ptr; + sljit_ub *buf_end; + sljit_ub len; + + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_const *const_; + + CHECK_ERROR_PTR(); + check_sljit_generate_code(compiler); + reverse_buf(compiler); + + /* Second code generation pass. */ + code = (sljit_ub*)SLJIT_MALLOC_EXEC(compiler->size); + PTR_FAIL_WITH_EXEC_IF(code); + buf = compiler->buf; + + code_ptr = code; + label = compiler->labels; + jump = compiler->jumps; + const_ = compiler->consts; + do { + buf_ptr = buf->memory; + buf_end = buf_ptr + buf->used_size; + do { + len = *buf_ptr++; + if (len > 0) { + /* The code is already generated. */ + SLJIT_MEMMOVE(code_ptr, buf_ptr, len); + code_ptr += len; + buf_ptr += len; + } + else { + if (*buf_ptr >= 4) { + jump->addr = (sljit_uw)code_ptr; + if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) + code_ptr = generate_near_jump_code(jump, code_ptr, code, *buf_ptr - 4); + else + code_ptr = generate_far_jump_code(jump, code_ptr, *buf_ptr - 4); + jump = jump->next; + } + else if (*buf_ptr == 0) { + label->addr = (sljit_uw)code_ptr; + label->size = code_ptr - code; + label = label->next; + } + else if (*buf_ptr == 1) { + const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_w); + const_ = const_->next; + } + else { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + *code_ptr++ = (*buf_ptr == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */; + buf_ptr++; + *(sljit_w*)code_ptr = *(sljit_w*)buf_ptr - ((sljit_w)code_ptr + sizeof(sljit_w)); + code_ptr += sizeof(sljit_w); + buf_ptr += sizeof(sljit_w) - 1; +#else + code_ptr = generate_fixed_jump(code_ptr, *(sljit_w*)(buf_ptr + 1), *buf_ptr); + buf_ptr += sizeof(sljit_w); +#endif + } + buf_ptr++; + } + } while (buf_ptr < buf_end); + SLJIT_ASSERT(buf_ptr == buf_end); + buf = buf->next; + } while (buf); + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!const_); + + jump = compiler->jumps; + while (jump) { + if (jump->flags & PATCH_MB) { + SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) >= -128 && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))) <= 127); + *(sljit_ub*)jump->addr = (sljit_ub)(jump->u.label->addr - (jump->addr + sizeof(sljit_b))); + } else if (jump->flags & PATCH_MW) { + if (jump->flags & JUMP_LABEL) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + *(sljit_w*)jump->addr = (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_w))); +#else + SLJIT_ASSERT((sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll); + *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.label->addr - (jump->addr + sizeof(sljit_hw))); +#endif + } + else { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + *(sljit_w*)jump->addr = (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_w))); +#else + SLJIT_ASSERT((sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) >= -0x80000000ll && (sljit_w)(jump->u.target - (jump->addr + sizeof(sljit_hw))) <= 0x7fffffffll); + *(sljit_hw*)jump->addr = (sljit_hw)(jump->u.target - (jump->addr + sizeof(sljit_hw))); +#endif + } + } +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + else if (jump->flags & PATCH_MD) + *(sljit_w*)jump->addr = jump->u.label->addr; +#endif + + jump = jump->next; + } + + /* Maybe we waste some space because of short jumps. */ + SLJIT_ASSERT(code_ptr <= code + compiler->size); + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_size = compiler->size; + return (void*)code; +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +static int emit_cum_binary(struct sljit_compiler *compiler, + sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + +static int emit_non_cum_binary(struct sljit_compiler *compiler, + sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w); + +static int emit_mov(struct sljit_compiler *compiler, + int dst, sljit_w dstw, + int src, sljit_w srcw); + +static SLJIT_INLINE int emit_save_flags(struct sljit_compiler *compiler) +{ + sljit_ub *buf; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); + FAIL_IF(!buf); + INC_SIZE(5); + *buf++ = 0x9c; /* pushfd */ +#else + buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); + FAIL_IF(!buf); + INC_SIZE(6); + *buf++ = 0x9c; /* pushfq */ + *buf++ = 0x48; +#endif + *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp + sizeof(sljit_w)] */ + *buf++ = 0x64; + *buf++ = 0x24; + *buf++ = sizeof(sljit_w); + compiler->flags_saved = 1; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_restore_flags(struct sljit_compiler *compiler, int keep_flags) +{ + sljit_ub *buf; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + buf = (sljit_ub*)ensure_buf(compiler, 1 + 5); + FAIL_IF(!buf); + INC_SIZE(5); +#else + buf = (sljit_ub*)ensure_buf(compiler, 1 + 6); + FAIL_IF(!buf); + INC_SIZE(6); + *buf++ = 0x48; +#endif + *buf++ = 0x8d; /* lea esp/rsp, [esp/rsp - sizeof(sljit_w)] */ + *buf++ = 0x64; + *buf++ = 0x24; + *buf++ = (sljit_ub)-(int)sizeof(sljit_w); + *buf++ = 0x9d; /* popfd / popfq */ + compiler->flags_saved = keep_flags; + return SLJIT_SUCCESS; +} + +#ifdef _WIN32 +#include + +static void SLJIT_CALL sljit_touch_stack(sljit_w local_size) +{ + /* Workaround for calling _chkstk. */ + alloca(local_size); +} +#endif + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +#include "sljitNativeX86_32.c" +#else +#include "sljitNativeX86_64.c" +#endif + +static int emit_mov(struct sljit_compiler *compiler, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + + if (dst == SLJIT_UNUSED) { + /* No destination, doesn't need to setup flags. */ + if (src & SLJIT_MEM) { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw); + FAIL_IF(!code); + *code = 0x8b; + } + return SLJIT_SUCCESS; + } + if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) { + code = emit_x86_instruction(compiler, 1, src, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x89; + return SLJIT_SUCCESS; + } + if (src & SLJIT_IMM) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw); +#else + if (!compiler->mode32) { + if (NOT_HALFWORD(srcw)) + return emit_load_imm64(compiler, dst, srcw); + } + else + return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, 0xb8 + reg_lmap[dst], srcw); +#endif + } +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (!compiler->mode32 && NOT_HALFWORD(srcw)) { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, srcw)); + code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x89; + return SLJIT_SUCCESS; + } +#endif + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc7; + return SLJIT_SUCCESS; + } + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) { + code = emit_x86_instruction(compiler, 1, dst, 0, src, srcw); + FAIL_IF(!code); + *code = 0x8b; + return SLJIT_SUCCESS; + } + + /* Memory to memory move. Requires two instruction. */ + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src, srcw); + FAIL_IF(!code); + *code = 0x8b; + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x89; + return SLJIT_SUCCESS; +} + +#define EMIT_MOV(compiler, dst, dstw, src, srcw) \ + FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op) +{ + sljit_ub *buf; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + int size; +#endif + + CHECK_ERROR(); + check_sljit_emit_op0(compiler, op); + + switch (GET_OPCODE(op)) { + case SLJIT_BREAKPOINT: + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + *buf = 0xcc; + break; + case SLJIT_NOP: + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + *buf = 0x90; + break; + case SLJIT_UMUL: + case SLJIT_SMUL: + case SLJIT_UDIV: + case SLJIT_SDIV: + compiler->flags_saved = 0; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) +#ifdef _WIN64 + SLJIT_COMPILE_ASSERT( + reg_map[SLJIT_TEMPORARY_REG1] == 0 + && reg_map[SLJIT_TEMPORARY_REG2] == 2 + && reg_map[TMP_REGISTER] > 7, + invalid_register_assignment_for_div_mul); +#else + SLJIT_COMPILE_ASSERT( + reg_map[SLJIT_TEMPORARY_REG1] == 0 + && reg_map[SLJIT_TEMPORARY_REG2] < 7 + && reg_map[TMP_REGISTER] == 2, + invalid_register_assignment_for_div_mul); +#endif + compiler->mode32 = op & SLJIT_INT_OP; +#endif + + op = GET_OPCODE(op); + if (op == SLJIT_UDIV) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0); + buf = emit_x86_instruction(compiler, 1, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0); +#else + buf = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0); +#endif + FAIL_IF(!buf); + *buf = 0x33; + } + + if (op == SLJIT_SDIV) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0); +#endif + + /* CDQ instruction */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + *buf = 0x99; +#else + if (compiler->mode32) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!buf); + INC_SIZE(1); + *buf = 0x99; + } else { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + INC_SIZE(2); + *buf++ = REX_W; + *buf = 0x99; + } +#endif + } + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + INC_SIZE(2); + *buf++ = 0xf7; + *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_map[TMP_REGISTER] : reg_map[SLJIT_TEMPORARY_REG2]); +#else +#ifdef _WIN64 + size = (!compiler->mode32 || op >= SLJIT_UDIV) ? 3 : 2; +#else + size = (!compiler->mode32) ? 3 : 2; +#endif + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + INC_SIZE(size); +#ifdef _WIN64 + if (!compiler->mode32) + *buf++ = REX_W | ((op >= SLJIT_UDIV) ? REX_B : 0); + else if (op >= SLJIT_UDIV) + *buf++ = REX_B; + *buf++ = 0xf7; + *buf = 0xc0 | ((op >= SLJIT_UDIV) ? reg_lmap[TMP_REGISTER] : reg_lmap[SLJIT_TEMPORARY_REG2]); +#else + if (!compiler->mode32) + *buf++ = REX_W; + *buf++ = 0xf7; + *buf = 0xc0 | reg_map[SLJIT_TEMPORARY_REG2]; +#endif +#endif + switch (op) { + case SLJIT_UMUL: + *buf |= 4 << 3; + break; + case SLJIT_SMUL: + *buf |= 5 << 3; + break; + case SLJIT_UDIV: + *buf |= 6 << 3; + break; + case SLJIT_SDIV: + *buf |= 7 << 3; + break; + } +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) + EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, TMP_REGISTER, 0); +#endif + break; + } + + return SLJIT_SUCCESS; +} + +#define ENCODE_PREFIX(prefix) \ + do { \ + code = (sljit_ub*)ensure_buf(compiler, 1 + 1); \ + FAIL_IF(!code); \ + INC_CSIZE(1); \ + *code = (prefix); \ + } while (0) + +static int emit_mov_byte(struct sljit_compiler *compiler, int sign, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + int dst_r; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + int work_r; +#endif + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + + if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) + return SLJIT_SUCCESS; /* Empty instruction. */ + + if (src & SLJIT_IMM) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw); +#else + return emit_load_imm64(compiler, dst, srcw); +#endif + } + code = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc6; + return SLJIT_SUCCESS; + } + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER; + + if ((dst & SLJIT_MEM) && src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (reg_map[src] >= 4) { + SLJIT_ASSERT(dst_r == TMP_REGISTER); + EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0); + } else + dst_r = src; +#else + dst_r = src; +#endif + } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + else if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS && reg_map[src] >= 4) { + /* src, dst are registers. */ + SLJIT_ASSERT(dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER); + if (reg_map[dst] < 4) { + if (dst != src) + EMIT_MOV(compiler, dst, 0, src, 0); + code = emit_x86_instruction(compiler, 2, dst, 0, dst, 0); + FAIL_IF(!code); + *code++ = 0x0f; + *code = sign ? 0xbe : 0xb6; + } + else { + if (dst != src) + EMIT_MOV(compiler, dst, 0, src, 0); + if (sign) { + /* shl reg, 24 */ + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); + FAIL_IF(!code); + *code |= 0x4 << 3; + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 24, dst, 0); + FAIL_IF(!code); + /* shr/sar reg, 24 */ + *code |= 0x7 << 3; + } + else { + /* and dst, 0xff */ + code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 255, dst, 0); + FAIL_IF(!code); + *(code + 1) |= 0x4 << 3; + } + } + return SLJIT_SUCCESS; + } +#endif + else { + /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */ + code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); + FAIL_IF(!code); + *code++ = 0x0f; + *code = sign ? 0xbe : 0xb6; + } + + if (dst & SLJIT_MEM) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst_r == TMP_REGISTER) { + /* Find a non-used register, whose reg_map[src] < 4. */ + if ((dst & 0xf) == SLJIT_TEMPORARY_REG1) { + if ((dst & 0xf0) == (SLJIT_TEMPORARY_REG2 << 4)) + work_r = SLJIT_TEMPORARY_REG3; + else + work_r = SLJIT_TEMPORARY_REG2; + } + else { + if ((dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4)) + work_r = SLJIT_TEMPORARY_REG1; + else if ((dst & 0xf) == SLJIT_TEMPORARY_REG2) + work_r = SLJIT_TEMPORARY_REG3; + else + work_r = SLJIT_TEMPORARY_REG2; + } + + if (work_r == SLJIT_TEMPORARY_REG1) { + ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]); + } + else { + code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); + FAIL_IF(!code); + *code = 0x87; + } + + code = emit_x86_instruction(compiler, 1, work_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x88; + + if (work_r == SLJIT_TEMPORARY_REG1) { + ENCODE_PREFIX(0x90 + reg_map[TMP_REGISTER]); + } + else { + code = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0); + FAIL_IF(!code); + *code = 0x87; + } + } + else { + code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x88; + } +#else + code = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x88; +#endif + } + + return SLJIT_SUCCESS; +} + +static int emit_mov_half(struct sljit_compiler *compiler, int sign, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + int dst_r; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + + if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM)) + return SLJIT_SUCCESS; /* Empty instruction. */ + + if (src & SLJIT_IMM) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + return emit_do_imm(compiler, 0xb8 + reg_map[dst], srcw); +#else + return emit_load_imm64(compiler, dst, srcw); +#endif + } + code = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw); + FAIL_IF(!code); + *code = 0xc7; + return SLJIT_SUCCESS; + } + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REGISTER; + + if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS)) + dst_r = src; + else { + code = emit_x86_instruction(compiler, 2, dst_r, 0, src, srcw); + FAIL_IF(!code); + *code++ = 0x0f; + *code = sign ? 0xbf : 0xb7; + } + + if (dst & SLJIT_MEM) { + code = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x89; + } + + return SLJIT_SUCCESS; +} + +static int emit_unary(struct sljit_compiler *compiler, int un_index, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + + if (dst == SLJIT_UNUSED) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= (un_index) << 3; + return SLJIT_SUCCESS; + } + if (dst == src && dstw == srcw) { + /* Same input and output */ + code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= (un_index) << 3; + return SLJIT_SUCCESS; + } + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + EMIT_MOV(compiler, dst, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= (un_index) << 3; + return SLJIT_SUCCESS; + } + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= (un_index) << 3; + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + return SLJIT_SUCCESS; +} + +static int emit_not_with_flags(struct sljit_compiler *compiler, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + + if (dst == SLJIT_UNUSED) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= 0x2 << 3; + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code = 0x0b; + return SLJIT_SUCCESS; + } + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + EMIT_MOV(compiler, dst, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= 0x2 << 3; + code = emit_x86_instruction(compiler, 1, dst, 0, dst, 0); + FAIL_IF(!code); + *code = 0x0b; + return SLJIT_SUCCESS; + } + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= 0x2 << 3; + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code = 0x0b; + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + return SLJIT_SUCCESS; +} + +static int emit_clz(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + int dst_r; + + SLJIT_UNUSED_ARG(op); + if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { + /* Just set the zero flag. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + code = emit_x86_instruction(compiler, 1, 0, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0xf7; + *code |= 0x2 << 3; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 31, TMP_REGISTER, 0); +#else + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, TMP_REGISTER, 0); +#endif + FAIL_IF(!code); + *code |= 0x5 << 3; + return SLJIT_SUCCESS; + } + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + src = TMP_REGISTER; + srcw = 0; + } + + code = emit_x86_instruction(compiler, 2, TMP_REGISTER, 0, src, srcw); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xbd; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) + dst_r = dst; + else { + /* Find an unused temporary register. */ + if ((dst & 0xf) != SLJIT_TEMPORARY_REG1 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG1 << 4)) + dst_r = SLJIT_TEMPORARY_REG1; + else if ((dst & 0xf) != SLJIT_TEMPORARY_REG2 && (dst & 0xf0) != (SLJIT_TEMPORARY_REG2 << 4)) + dst_r = SLJIT_TEMPORARY_REG2; + else + dst_r = SLJIT_TEMPORARY_REG3; + EMIT_MOV(compiler, dst, dstw, dst_r, 0); + } + EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, 32 + 31); +#else + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) ? dst : TMP_REG2; + compiler->mode32 = 0; + EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 64 + 63 : 32 + 31); + compiler->mode32 = op & SLJIT_INT_OP; +#endif + + code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0x45; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0); +#else + code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op & SLJIT_INT_OP) ? 63 : 31, dst_r, 0); +#endif + FAIL_IF(!code); + *(code + 1) |= 0x6 << 3; + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (dst & SLJIT_MEM) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x87; + } +#else + if (dst & SLJIT_MEM) + EMIT_MOV(compiler, dst, dstw, TMP_REG2, 0); +#endif + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + sljit_ub* code; + int update = 0; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + int dst_is_ereg = 0; + int src_is_ereg = 0; +#else + #define src_is_ereg 0 +#endif + + CHECK_ERROR(); + check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_INT_OP; +#endif + CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1); + CHECK_EXTRA_REGS(src, srcw, src_is_ereg = 1); + + if (GET_OPCODE(op) >= SLJIT_MOV && GET_OPCODE(op) <= SLJIT_MOVU_SI) { + op = GET_OPCODE(op); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; +#endif + + SLJIT_COMPILE_ASSERT(SLJIT_MOV + 7 == SLJIT_MOVU, movu_offset); + if (op >= SLJIT_MOVU) { + update = 1; + op -= 7; + } + + if (src & SLJIT_IMM) { + switch (op) { + case SLJIT_MOV_UB: + srcw = (unsigned char)srcw; + break; + case SLJIT_MOV_SB: + srcw = (signed char)srcw; + break; + case SLJIT_MOV_UH: + srcw = (unsigned short)srcw; + break; + case SLJIT_MOV_SH: + srcw = (signed short)srcw; + break; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + case SLJIT_MOV_UI: + srcw = (unsigned int)srcw; + break; + case SLJIT_MOV_SI: + srcw = (signed int)srcw; + break; +#endif + } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (SLJIT_UNLIKELY(dst_is_ereg)) + return emit_mov(compiler, dst, dstw, src, srcw); +#endif + } + + if (SLJIT_UNLIKELY(update) && (src & SLJIT_MEM) && !src_is_ereg && (src & 0xf) && (srcw != 0 || (src & 0xf0) != 0)) { + code = emit_x86_instruction(compiler, 1, src & 0xf, 0, src, srcw); + FAIL_IF(!code); + *code = 0x8d; + src &= SLJIT_MEM | 0xf; + srcw = 0; + } + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_UI || op == SLJIT_MOV_SI) || (src & SLJIT_MEM))) { + SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_LOCALS_REG)); + dst = TMP_REGISTER; + } +#endif + + switch (op) { + case SLJIT_MOV: +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + case SLJIT_MOV_UI: + case SLJIT_MOV_SI: +#endif + FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw)); + break; + case SLJIT_MOV_UB: + FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned char)srcw : srcw)); + break; + case SLJIT_MOV_SB: + FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed char)srcw : srcw)); + break; + case SLJIT_MOV_UH: + FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned short)srcw : srcw)); + break; + case SLJIT_MOV_SH: + FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed short)srcw : srcw)); + break; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + case SLJIT_MOV_UI: + FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, (src & SLJIT_IMM) ? (unsigned int)srcw : srcw)); + break; + case SLJIT_MOV_SI: + FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, (src & SLJIT_IMM) ? (signed int)srcw : srcw)); + break; +#endif + } + +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REGISTER) + return emit_mov(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), dstw, TMP_REGISTER, 0); +#endif + + if (SLJIT_UNLIKELY(update) && (dst & SLJIT_MEM) && (dst & 0xf) && (dstw != 0 || (dst & 0xf0) != 0)) { + code = emit_x86_instruction(compiler, 1, dst & 0xf, 0, dst, dstw); + FAIL_IF(!code); + *code = 0x8d; + } + return SLJIT_SUCCESS; + } + + if (SLJIT_UNLIKELY(GET_FLAGS(op))) + compiler->flags_saved = 0; + + switch (GET_OPCODE(op)) { + case SLJIT_NOT: + if (SLJIT_UNLIKELY(op & SLJIT_SET_E)) + return emit_not_with_flags(compiler, dst, dstw, src, srcw); + return emit_unary(compiler, 0x2, dst, dstw, src, srcw); + + case SLJIT_NEG: + if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) + FAIL_IF(emit_save_flags(compiler)); + return emit_unary(compiler, 0x3, dst, dstw, src, srcw); + + case SLJIT_CLZ: + if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) + FAIL_IF(emit_save_flags(compiler)); + return emit_clz(compiler, op, dst, dstw, src, srcw); + } + + return SLJIT_SUCCESS; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + #undef src_is_ereg +#endif +} + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + +#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \ + if (IS_HALFWORD(immw) || compiler->mode32) { \ + code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \ + FAIL_IF(!code); \ + *(code + 1) |= (_op_imm_); \ + } \ + else { \ + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immw)); \ + code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, arg, argw); \ + FAIL_IF(!code); \ + *code = (_op_mr_); \ + } + +#define BINARY_EAX_IMM(_op_eax_imm_, immw) \ + FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (_op_eax_imm_), immw)) + +#else + +#define BINARY_IMM(_op_imm_, _op_mr_, immw, arg, argw) \ + code = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \ + FAIL_IF(!code); \ + *(code + 1) |= (_op_imm_); + +#define BINARY_EAX_IMM(_op_eax_imm_, immw) \ + FAIL_IF(emit_do_imm(compiler, (_op_eax_imm_), immw)) + +#endif + +static int emit_cum_binary(struct sljit_compiler *compiler, + sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + + if (dst == SLJIT_UNUSED) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0); + } + else { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + return SLJIT_SUCCESS; + } + + if (dst == src1 && dstw == src1w) { + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { +#else + if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) { +#endif + BINARY_EAX_IMM(op_eax_imm, src2w); + } + else { + BINARY_IMM(op_imm, op_mr, src2w, dst, dstw); + } + } + else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= TMP_REGISTER) { + /* Special exception for sljit_emit_cond_value. */ + code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w); + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + return SLJIT_SUCCESS; + } + + /* Only for cumulative operations. */ + if (dst == src2 && dstw == src2w) { + if (src1 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { +#else + if ((dst == SLJIT_TEMPORARY_REG1) && (src1w > 127 || src1w < -128)) { +#endif + BINARY_EAX_IMM(op_eax_imm, src1w); + } + else { + BINARY_IMM(op_imm, op_mr, src1w, dst, dstw); + } + } + else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + code = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w); + FAIL_IF(!code); + *code = op_rm; + } + else if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { + code = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + return SLJIT_SUCCESS; + } + + /* General version. */ + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + EMIT_MOV(compiler, dst, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, dst, 0); + } + else { + code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + } + else { + /* This version requires less memory writing. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0); + } + else { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + } + + return SLJIT_SUCCESS; +} + +static int emit_non_cum_binary(struct sljit_compiler *compiler, + sljit_ub op_rm, sljit_ub op_mr, sljit_ub op_imm, sljit_ub op_eax_imm, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + + if (dst == SLJIT_UNUSED) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0); + } + else { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + return SLJIT_SUCCESS; + } + + if (dst == src1 && dstw == src1w) { + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { +#else + if ((dst == SLJIT_TEMPORARY_REG1) && (src2w > 127 || src2w < -128)) { +#endif + BINARY_EAX_IMM(op_eax_imm, src2w); + } + else { + BINARY_IMM(op_imm, op_mr, src2w, dst, dstw); + } + } + else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + code = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) { + code = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, src2, src2w); + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, dst, dstw); + FAIL_IF(!code); + *code = op_mr; + } + return SLJIT_SUCCESS; + } + + /* General version. */ + if ((dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) && dst != src2) { + EMIT_MOV(compiler, dst, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, dst, 0); + } + else { + code = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + } + else { + /* This version requires less memory writing. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + if (src2 & SLJIT_IMM) { + BINARY_IMM(op_imm, op_mr, src2w, TMP_REGISTER, 0); + } + else { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = op_rm; + } + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + } + + return SLJIT_SUCCESS; +} + +static int emit_mul(struct sljit_compiler *compiler, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + int dst_r; + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; + + /* Register destination. */ + if (dst_r == src1 && !(src2 & SLJIT_IMM)) { + code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xaf; + } + else if (dst_r == src2 && !(src1 & SLJIT_IMM)) { + code = emit_x86_instruction(compiler, 2, dst_r, 0, src1, src1w); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xaf; + } + else if (src1 & SLJIT_IMM) { + if (src2 & SLJIT_IMM) { + EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w); + src2 = dst_r; + src2w = 0; + } + + if (src1w <= 127 && src1w >= -128) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x6b; + code = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!code); + INC_CSIZE(1); + *code = (sljit_b)src1w; + } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + else { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x69; + code = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!code); + INC_CSIZE(4); + *(sljit_w*)code = src1w; + } +#else + else if (IS_HALFWORD(src1w)) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x69; + code = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!code); + INC_CSIZE(4); + *(sljit_hw*)code = (sljit_hw)src1w; + } + else { + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w); + if (dst_r != src2) + EMIT_MOV(compiler, dst_r, 0, src2, src2w); + code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xaf; + } +#endif + } + else if (src2 & SLJIT_IMM) { + /* Note: src1 is NOT immediate. */ + + if (src2w <= 127 && src2w >= -128) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); + FAIL_IF(!code); + *code = 0x6b; + code = (sljit_ub*)ensure_buf(compiler, 1 + 1); + FAIL_IF(!code); + INC_CSIZE(1); + *code = (sljit_b)src2w; + } +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + else { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); + FAIL_IF(!code); + *code = 0x69; + code = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!code); + INC_CSIZE(4); + *(sljit_w*)code = src2w; + } +#else + else if (IS_HALFWORD(src2w)) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w); + FAIL_IF(!code); + *code = 0x69; + code = (sljit_ub*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!code); + INC_CSIZE(4); + *(sljit_hw*)code = (sljit_hw)src2w; + } + else { + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, src1w); + if (dst_r != src1) + EMIT_MOV(compiler, dst_r, 0, src1, src1w); + code = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xaf; + } +#endif + } + else { + /* Neither argument is immediate. */ + if (ADDRESSING_DEPENDS_ON(src2, dst_r)) + dst_r = TMP_REGISTER; + EMIT_MOV(compiler, dst_r, 0, src1, src1w); + code = emit_x86_instruction(compiler, 2, dst_r, 0, src2, src2w); + FAIL_IF(!code); + *code++ = 0x0f; + *code = 0xaf; + } + + if (dst_r == TMP_REGISTER) + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + + return SLJIT_SUCCESS; +} + +static int emit_lea_binary(struct sljit_compiler *compiler, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + int dst_r, done = 0; + + /* These cases better be left to handled by normal way. */ + if (dst == src1 && dstw == src1w) + return SLJIT_ERR_UNSUPPORTED; + if (dst == src2 && dstw == src2w) + return SLJIT_ERR_UNSUPPORTED; + + dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; + + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) { + /* It is not possible to be both SLJIT_LOCALS_REG. */ + if (src1 != SLJIT_LOCALS_REG || src2 != SLJIT_LOCALS_REG) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0); + FAIL_IF(!code); + *code = 0x8d; + done = 1; + } + } +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((src2 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src2w))) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (int)src2w); +#else + if (src2 & SLJIT_IMM) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w); +#endif + FAIL_IF(!code); + *code = 0x8d; + done = 1; + } + } + else if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((src1 & SLJIT_IMM) && (compiler->mode32 || IS_HALFWORD(src1w))) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (int)src1w); +#else + if (src1 & SLJIT_IMM) { + code = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w); +#endif + FAIL_IF(!code); + *code = 0x8d; + done = 1; + } + } + + if (done) { + if (dst_r == TMP_REGISTER) + return emit_mov(compiler, dst, dstw, TMP_REGISTER, 0); + return SLJIT_SUCCESS; + } + return SLJIT_ERR_UNSUPPORTED; +} + +static int emit_cmp_binary(struct sljit_compiler *compiler, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { +#else + if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { +#endif + BINARY_EAX_IMM(0x3d, src2w); + return SLJIT_SUCCESS; + } + + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { + if (src2 & SLJIT_IMM) { + BINARY_IMM(0x7 << 3, 0x39, src2w, src1, 0); + } + else { + code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x3b; + } + return SLJIT_SUCCESS; + } + + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS && !(src1 & SLJIT_IMM)) { + code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); + FAIL_IF(!code); + *code = 0x39; + return SLJIT_SUCCESS; + } + + if (src2 & SLJIT_IMM) { + if (src1 & SLJIT_IMM) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + src1 = TMP_REGISTER; + src1w = 0; + } + BINARY_IMM(0x7 << 3, 0x39, src2w, src1, src1w); + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x3b; + } + return SLJIT_SUCCESS; +} + +static int emit_test_binary(struct sljit_compiler *compiler, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) { +#else + if (src1 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src2w > 127 || src2w < -128)) { +#endif + BINARY_EAX_IMM(0xa9, src2w); + return SLJIT_SUCCESS; + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (src2 == SLJIT_TEMPORARY_REG1 && (src2 & SLJIT_IMM) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) { +#else + if (src2 == SLJIT_TEMPORARY_REG1 && (src1 & SLJIT_IMM) && (src1w > 127 || src1w < -128)) { +#endif + BINARY_EAX_IMM(0xa9, src1w); + return SLJIT_SUCCESS; + } + + if (src1 >= SLJIT_TEMPORARY_REG1 && src1 <= SLJIT_NO_REGISTERS) { + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (IS_HALFWORD(src2w) || compiler->mode32) { + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + FAIL_IF(!code); + *code = 0xf7; + } + else { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); + code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0); + FAIL_IF(!code); + *code = 0x85; + } +#else + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + FAIL_IF(!code); + *code = 0xf7; +#endif + } + else { + code = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x85; + } + return SLJIT_SUCCESS; + } + + if (src2 >= SLJIT_TEMPORARY_REG1 && src2 <= SLJIT_NO_REGISTERS) { + if (src1 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (IS_HALFWORD(src1w) || compiler->mode32) { + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0); + FAIL_IF(!code); + *code = 0xf7; + } + else { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); + code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0); + FAIL_IF(!code); + *code = 0x85; + } +#else + code = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0); + FAIL_IF(!code); + *code = 0xf7; +#endif + } + else { + code = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); + FAIL_IF(!code); + *code = 0x85; + } + return SLJIT_SUCCESS; + } + + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (IS_HALFWORD(src2w) || compiler->mode32) { + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0); + FAIL_IF(!code); + *code = 0xf7; + } + else { + FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); + code = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code = 0x85; + } +#else + code = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REGISTER, 0); + FAIL_IF(!code); + *code = 0xf7; +#endif + } + else { + code = emit_x86_instruction(compiler, 1, TMP_REGISTER, 0, src2, src2w); + FAIL_IF(!code); + *code = 0x85; + } + return SLJIT_SUCCESS; +} + +static int emit_shift(struct sljit_compiler *compiler, + sljit_ub mode, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + sljit_ub* code; + + if ((src2 & SLJIT_IMM) || (src2 == SLJIT_PREF_SHIFT_REG)) { + if (dst == src1 && dstw == src1w) { + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw); + FAIL_IF(!code); + *code |= mode; + return SLJIT_SUCCESS; + } + if (dst == SLJIT_UNUSED) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0); + FAIL_IF(!code); + *code |= mode; + return SLJIT_SUCCESS; + } + if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code |= mode; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + return SLJIT_SUCCESS; + } + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) { + EMIT_MOV(compiler, dst, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0); + FAIL_IF(!code); + *code |= mode; + return SLJIT_SUCCESS; + } + + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REGISTER, 0); + FAIL_IF(!code); + *code |= mode; + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + return SLJIT_SUCCESS; + } + + if (dst == SLJIT_PREF_SHIFT_REG) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code |= mode; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + } + else if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) { + if (src1 != dst) + EMIT_MOV(compiler, dst, 0, src1, src1w); + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_PREF_SHIFT_REG, 0); + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0); + FAIL_IF(!code); + *code |= mode; + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + } + else { + /* This case is really difficult, since ecx itself may used for + addressing, and we must ensure to work even in that case. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, src1, src1w); +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0); +#else + /* [esp - 4] is reserved for eflags. */ + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w)), SLJIT_PREF_SHIFT_REG, 0); +#endif + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w); + code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REGISTER, 0); + FAIL_IF(!code); + *code |= mode; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0); +#else + /* [esp - 4] is reserved for eflags. */ + EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), -(int)(2 * sizeof(sljit_w))); +#endif + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + } + + return SLJIT_SUCCESS; +} + +static int emit_shift_with_flags(struct sljit_compiler *compiler, + sljit_ub mode, int set_flags, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + /* The CPU does not set flags if the shift count is 0. */ + if (src2 & SLJIT_IMM) { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if ((src2w & 0x3f) != 0 || (compiler->mode32 && (src2w & 0x1f) != 0)) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); +#else + if ((src2w & 0x1f) != 0) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); +#endif + if (!set_flags) + return emit_mov(compiler, dst, dstw, src1, src1w); + /* OR dst, src, 0 */ + return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d, + dst, dstw, src1, src1w, SLJIT_IMM, 0); + } + + if (!set_flags) + return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w); + + if (!(dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)) + FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0)); + + FAIL_IF(emit_shift(compiler,mode, dst, dstw, src1, src1w, src2, src2w)); + + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) + return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0); + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + CHECK_ERROR(); + check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = op & SLJIT_INT_OP; +#endif + CHECK_EXTRA_REGS(dst, dstw, (void)0); + CHECK_EXTRA_REGS(src1, src1w, (void)0); + CHECK_EXTRA_REGS(src2, src2w, (void)0); + + if (GET_OPCODE(op) >= SLJIT_MUL) { + if (SLJIT_UNLIKELY(GET_FLAGS(op))) + compiler->flags_saved = 0; + else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) + FAIL_IF(emit_save_flags(compiler)); + } + + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + if (!GET_FLAGS(op)) { + if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED) + return compiler->error; + } + else + compiler->flags_saved = 0; + if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) + FAIL_IF(emit_save_flags(compiler)); + return emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ADDC: + if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */ + FAIL_IF(emit_restore_flags(compiler, 1)); + else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS)) + FAIL_IF(emit_save_flags(compiler)); + if (SLJIT_UNLIKELY(GET_FLAGS(op))) + compiler->flags_saved = 0; + return emit_cum_binary(compiler, 0x13, 0x11, 0x2 << 3, 0x15, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_SUB: + if (!GET_FLAGS(op)) { + if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) + return compiler->error; + } + else + compiler->flags_saved = 0; + if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS) && !compiler->flags_saved) + FAIL_IF(emit_save_flags(compiler)); + if (dst == SLJIT_UNUSED) + return emit_cmp_binary(compiler, src1, src1w, src2, src2w); + return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_SUBC: + if (SLJIT_UNLIKELY(compiler->flags_saved)) /* C flag must be restored. */ + FAIL_IF(emit_restore_flags(compiler, 1)); + else if (SLJIT_UNLIKELY(op & SLJIT_KEEP_FLAGS)) + FAIL_IF(emit_save_flags(compiler)); + if (SLJIT_UNLIKELY(GET_FLAGS(op))) + compiler->flags_saved = 0; + return emit_non_cum_binary(compiler, 0x1b, 0x19, 0x3 << 3, 0x1d, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_MUL: + return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w); + case SLJIT_AND: + if (dst == SLJIT_UNUSED) + return emit_test_binary(compiler, src1, src1w, src2, src2w); + return emit_cum_binary(compiler, 0x23, 0x21, 0x4 << 3, 0x25, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_OR: + return emit_cum_binary(compiler, 0x0b, 0x09, 0x1 << 3, 0x0d, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_XOR: + return emit_cum_binary(compiler, 0x33, 0x31, 0x6 << 3, 0x35, + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_SHL: + return emit_shift_with_flags(compiler, 0x4 << 3, GET_FLAGS(op), + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_LSHR: + return emit_shift_with_flags(compiler, 0x5 << 3, GET_FLAGS(op), + dst, dstw, src1, src1w, src2, src2w); + case SLJIT_ASHR: + return emit_shift_with_flags(compiler, 0x7 << 3, GET_FLAGS(op), + dst, dstw, src1, src1w, src2, src2w); + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg) +{ + check_sljit_get_register_index(reg); +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + if (reg == SLJIT_TEMPORARY_EREG1 || reg == SLJIT_TEMPORARY_EREG2 + || reg == SLJIT_SAVED_EREG1 || reg == SLJIT_SAVED_EREG2) + return -1; +#endif + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, int size) +{ + sljit_ub *buf; + + CHECK_ERROR(); + check_sljit_emit_op_custom(compiler, instruction, size); + SLJIT_ASSERT(size > 0 && size < 16); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + size); + FAIL_IF(!buf); + INC_SIZE(size); + SLJIT_MEMMOVE(buf, instruction, size); + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +static int sse2_available = 0; +#endif + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + +/* Alignment + 2 * 16 bytes. */ +static sljit_i sse2_data[3 + 4 + 4]; +static sljit_i *sse2_buffer; + +static void init_compiler() +{ +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) + int features = 0; +#endif + + sse2_buffer = (sljit_i*)(((sljit_uw)sse2_data + 15) & ~0xf); + sse2_buffer[0] = 0; + sse2_buffer[1] = 0x80000000; + sse2_buffer[4] = 0xffffffff; + sse2_buffer[5] = 0x7fffffff; + +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +#ifdef __GNUC__ + /* AT&T syntax. */ + asm ( + "pushl %%ebx\n" + "movl $0x1, %%eax\n" + "cpuid\n" + "popl %%ebx\n" + "movl %%edx, %0\n" + : "=g" (features) + : + : "%eax", "%ecx", "%edx" + ); +#elif defined(_MSC_VER) || defined(__BORLANDC__) + /* Intel syntax. */ + __asm { + mov eax, 1 + push ebx + cpuid + pop ebx + mov features, edx + } +#else + #error "SLJIT_SSE2_AUTO is not implemented for this C compiler" +#endif + sse2_available = (features >> 26) & 0x1; +#endif +} + +#endif + +SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void) +{ + /* Always available. */ + return 1; +} + +#if (defined SLJIT_SSE2 && SLJIT_SSE2) + +static int emit_sse2(struct sljit_compiler *compiler, sljit_ub opcode, + int xmm1, int xmm2, sljit_w xmm2w) +{ + sljit_ub *buf; + + buf = emit_x86_instruction(compiler, 2 | EX86_PREF_F2 | EX86_SSE2, xmm1, 0, xmm2, xmm2w); + FAIL_IF(!buf); + *buf++ = 0x0f; + *buf = opcode; + return SLJIT_SUCCESS; +} + +static int emit_sse2_logic(struct sljit_compiler *compiler, sljit_ub opcode, + int xmm1, int xmm2, sljit_w xmm2w) +{ + sljit_ub *buf; + + buf = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2, xmm1, 0, xmm2, xmm2w); + FAIL_IF(!buf); + *buf++ = 0x0f; + *buf = opcode; + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int emit_sse2_load(struct sljit_compiler *compiler, + int dst, int src, sljit_w srcw) +{ + return emit_sse2(compiler, 0x10, dst, src, srcw); +} + +static SLJIT_INLINE int emit_sse2_store(struct sljit_compiler *compiler, + int dst, sljit_w dstw, int src) +{ + return emit_sse2(compiler, 0x11, src, dst, dstw); +} + +#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, +#else +static int sljit_emit_sse2_fop1(struct sljit_compiler *compiler, int op, +#endif + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + int dst_r; + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + if (GET_OPCODE(op) == SLJIT_FCMP) { + compiler->flags_saved = 0; + if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) + dst_r = dst; + else { + dst_r = TMP_FREG; + FAIL_IF(emit_sse2_load(compiler, dst_r, dst, dstw)); + } + return emit_sse2_logic(compiler, 0x2e, dst_r, src, srcw); + } + + if (op == SLJIT_FMOV) { + if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) + return emit_sse2_load(compiler, dst, src, srcw); + if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) + return emit_sse2_store(compiler, dst, dstw, src); + FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src, srcw)); + return emit_sse2_store(compiler, dst, dstw, TMP_FREG); + } + + if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) { + dst_r = dst; + if (dst != src) + FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw)); + } + else { + dst_r = TMP_FREG; + FAIL_IF(emit_sse2_load(compiler, dst_r, src, srcw)); + } + + switch (op) { + case SLJIT_FNEG: + FAIL_IF(emit_sse2_logic(compiler, 0x57, dst_r, SLJIT_MEM0(), (sljit_w)sse2_buffer)); + break; + + case SLJIT_FABS: + FAIL_IF(emit_sse2_logic(compiler, 0x54, dst_r, SLJIT_MEM0(), (sljit_w)(sse2_buffer + 4))); + break; + } + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; +} + +#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, +#else +static int sljit_emit_sse2_fop2(struct sljit_compiler *compiler, int op, +#endif + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + int dst_r; + + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + if (dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) { + dst_r = dst; + if (dst == src1) + ; /* Do nothing here. */ + else if (dst == src2 && (op == SLJIT_FADD || op == SLJIT_FMUL)) { + /* Swap arguments. */ + src2 = src1; + src2w = src1w; + } + else if (dst != src2) + FAIL_IF(emit_sse2_load(compiler, dst_r, src1, src1w)); + else { + dst_r = TMP_FREG; + FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w)); + } + } + else { + dst_r = TMP_FREG; + FAIL_IF(emit_sse2_load(compiler, TMP_FREG, src1, src1w)); + } + + switch (op) { + case SLJIT_FADD: + FAIL_IF(emit_sse2(compiler, 0x58, dst_r, src2, src2w)); + break; + + case SLJIT_FSUB: + FAIL_IF(emit_sse2(compiler, 0x5c, dst_r, src2, src2w)); + break; + + case SLJIT_FMUL: + FAIL_IF(emit_sse2(compiler, 0x59, dst_r, src2, src2w)); + break; + + case SLJIT_FDIV: + FAIL_IF(emit_sse2(compiler, 0x5e, dst_r, src2, src2w)); + break; + } + + if (dst_r == TMP_FREG) + return emit_sse2_store(compiler, dst, dstw, TMP_FREG); + return SLJIT_SUCCESS; +} + +#endif + +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) || !(defined SLJIT_SSE2 && SLJIT_SSE2) + +static int emit_fld(struct sljit_compiler *compiler, + int src, sljit_w srcw) +{ + sljit_ub *buf; + + if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + INC_SIZE(2); + *buf++ = 0xd9; + *buf = 0xc0 + src - 1; + return SLJIT_SUCCESS; + } + + buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); + FAIL_IF(!buf); + *buf = 0xdd; + return SLJIT_SUCCESS; +} + +static int emit_fop(struct sljit_compiler *compiler, + sljit_ub st_arg, sljit_ub st_arg2, + sljit_ub m64fp_arg, sljit_ub m64fp_arg2, + int src, sljit_w srcw) +{ + sljit_ub *buf; + + if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + INC_SIZE(2); + *buf++ = st_arg; + *buf = st_arg2 + src; + return SLJIT_SUCCESS; + } + + buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); + FAIL_IF(!buf); + *buf++ = m64fp_arg; + *buf |= m64fp_arg2; + return SLJIT_SUCCESS; +} + +static int emit_fop_regs(struct sljit_compiler *compiler, + sljit_ub st_arg, sljit_ub st_arg2, + int src) +{ + sljit_ub *buf; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!buf); + INC_SIZE(2); + *buf++ = st_arg; + *buf = st_arg2 + src; + return SLJIT_SUCCESS; +} + +#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, +#else +static int sljit_emit_fpu_fop1(struct sljit_compiler *compiler, int op, +#endif + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ +#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + sljit_ub *buf; +#endif + + CHECK_ERROR(); + check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + if (GET_OPCODE(op) == SLJIT_FCMP) { + compiler->flags_saved = 0; +#if !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + FAIL_IF(emit_fld(compiler, dst, dstw)); + FAIL_IF(emit_fop(compiler, 0xd8, 0xd8, 0xdc, 0x3 << 3, src, srcw)); + + /* Copy flags. */ + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); + buf = (sljit_ub*)ensure_buf(compiler, 1 + 3); + FAIL_IF(!buf); + INC_SIZE(3); + *buf++ = 0xdf; + *buf++ = 0xe0; + /* Note: lahf is not supported on all x86-64 architectures. */ + *buf++ = 0x9e; + EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0); +#else + if (src >= SLJIT_FLOAT_REG1 && src <= SLJIT_FLOAT_REG4) { + FAIL_IF(emit_fld(compiler, dst, dstw)); + FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src)); + } else { + FAIL_IF(emit_fld(compiler, src, srcw)); + FAIL_IF(emit_fld(compiler, dst + ((dst >= SLJIT_FLOAT_REG1 && dst <= SLJIT_FLOAT_REG4) ? 1 : 0), dstw)); + FAIL_IF(emit_fop_regs(compiler, 0xdf, 0xe8, src)); + FAIL_IF(emit_fop_regs(compiler, 0xdd, 0xd8, 0)); + } +#endif + return SLJIT_SUCCESS; + } + + FAIL_IF(emit_fld(compiler, src, srcw)); + + switch (op) { + case SLJIT_FNEG: + FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe0, 0)); + break; + case SLJIT_FABS: + FAIL_IF(emit_fop_regs(compiler, 0xd9, 0xe1, 0)); + break; + } + + FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw)); + + return SLJIT_SUCCESS; +} + +#if !(defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, +#else +static int sljit_emit_fpu_fop2(struct sljit_compiler *compiler, int op, +#endif + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + CHECK_ERROR(); + check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 1; +#endif + + if (src1 >= SLJIT_FLOAT_REG1 && src1 <= SLJIT_FLOAT_REG4 && dst == src1) { + FAIL_IF(emit_fld(compiler, src2, src2w)); + + switch (op) { + case SLJIT_FADD: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src1)); + break; + case SLJIT_FSUB: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe8, src1)); + break; + case SLJIT_FMUL: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src1)); + break; + case SLJIT_FDIV: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf8, src1)); + break; + } + return SLJIT_SUCCESS; + } + + FAIL_IF(emit_fld(compiler, src1, src1w)); + + if (src2 >= SLJIT_FLOAT_REG1 && src2 <= SLJIT_FLOAT_REG4 && dst == src2) { + switch (op) { + case SLJIT_FADD: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc0, src2)); + break; + case SLJIT_FSUB: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xe0, src2)); + break; + case SLJIT_FMUL: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xc8, src2)); + break; + case SLJIT_FDIV: + FAIL_IF(emit_fop_regs(compiler, 0xde, 0xf0, src2)); + break; + } + return SLJIT_SUCCESS; + } + + switch (op) { + case SLJIT_FADD: + FAIL_IF(emit_fop(compiler, 0xd8, 0xc0, 0xdc, 0x0 << 3, src2, src2w)); + break; + case SLJIT_FSUB: + FAIL_IF(emit_fop(compiler, 0xd8, 0xe0, 0xdc, 0x4 << 3, src2, src2w)); + break; + case SLJIT_FMUL: + FAIL_IF(emit_fop(compiler, 0xd8, 0xc8, 0xdc, 0x1 << 3, src2, src2w)); + break; + case SLJIT_FDIV: + FAIL_IF(emit_fop(compiler, 0xd8, 0xf0, 0xdc, 0x6 << 3, src2, src2w)); + break; + } + + FAIL_IF(emit_fop(compiler, 0xdd, 0xd8, 0xdd, 0x3 << 3, dst, dstw)); + + return SLJIT_SUCCESS; +} +#endif + +#if (defined SLJIT_SSE2_AUTO && SLJIT_SSE2_AUTO) + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src, sljit_w srcw) +{ + if (sse2_available) + return sljit_emit_sse2_fop1(compiler, op, dst, dstw, src, srcw); + else + return sljit_emit_fpu_fop1(compiler, op, dst, dstw, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op, + int dst, sljit_w dstw, + int src1, sljit_w src1w, + int src2, sljit_w src2w) +{ + if (sse2_available) + return sljit_emit_sse2_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + else + return sljit_emit_fpu_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w); +} + +#endif + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + sljit_ub *buf; + struct sljit_label *label; + + CHECK_ERROR_PTR(); + check_sljit_emit_label(compiler); + + /* We should restore the flags before the label, + since other taken jumps has their own flags as well. */ + if (SLJIT_UNLIKELY(compiler->flags_saved)) + PTR_FAIL_IF(emit_restore_flags(compiler, 0)); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + + buf = (sljit_ub*)ensure_buf(compiler, 2); + PTR_FAIL_IF(!buf); + + *buf++ = 0; + *buf++ = 0; + + return label; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type) +{ + sljit_ub *buf; + struct sljit_jump *jump; + + CHECK_ERROR_PTR(); + check_sljit_emit_jump(compiler, type); + + if (SLJIT_UNLIKELY(compiler->flags_saved)) { + if ((type & 0xff) <= SLJIT_JUMP) + PTR_FAIL_IF(emit_restore_flags(compiler, 0)); + compiler->flags_saved = 0; + } + + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF_NULL(jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + type &= 0xff; + + if (type >= SLJIT_CALL1) + PTR_FAIL_IF(call_with_args(compiler, type)); + + /* Worst case size. */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + compiler->size += (type >= SLJIT_JUMP) ? 5 : 6; +#else + compiler->size += (type >= SLJIT_JUMP) ? (10 + 3) : (2 + 10 + 3); +#endif + + buf = (sljit_ub*)ensure_buf(compiler, 2); + PTR_FAIL_IF_NULL(buf); + + *buf++ = 0; + *buf++ = type + 4; + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw) +{ + sljit_ub *code; + struct sljit_jump *jump; + + CHECK_ERROR(); + check_sljit_emit_ijump(compiler, type, src, srcw); + + CHECK_EXTRA_REGS(src, srcw, (void)0); + if (SLJIT_UNLIKELY(compiler->flags_saved)) { + if (type <= SLJIT_JUMP) + FAIL_IF(emit_restore_flags(compiler, 0)); + compiler->flags_saved = 0; + } + + if (type >= SLJIT_CALL1) { +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) + if (src == SLJIT_TEMPORARY_REG3) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0); + src = TMP_REGISTER; + } + if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG && type >= SLJIT_CALL3) { + if (src & 0xf0) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + src = TMP_REGISTER; + } + else + srcw += sizeof(sljit_w); + } +#else + if ((src & SLJIT_MEM) && (src & 0xf) == SLJIT_LOCALS_REG) { + if (src & 0xf0) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, srcw); + src = TMP_REGISTER; + } + else + srcw += sizeof(sljit_w) * (type - SLJIT_CALL0); + } +#endif +#endif +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && defined(_WIN64) + if (src == SLJIT_TEMPORARY_REG3) { + EMIT_MOV(compiler, TMP_REGISTER, 0, src, 0); + src = TMP_REGISTER; + } +#endif + FAIL_IF(call_with_args(compiler, type)); + } + + if (src == SLJIT_IMM) { + jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump)); + FAIL_IF_NULL(jump); + set_jump(jump, compiler, JUMP_ADDR); + jump->u.target = srcw; + + /* Worst case size. */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + compiler->size += 5; +#else + compiler->size += 10 + 3; +#endif + + code = (sljit_ub*)ensure_buf(compiler, 2); + FAIL_IF_NULL(code); + + *code++ = 0; + *code++ = type + 4; + } + else { +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + /* REX_W is not necessary (src is not immediate). */ + compiler->mode32 = 1; +#endif + code = emit_x86_instruction(compiler, 1, 0, 0, src, srcw); + FAIL_IF(!code); + *code++ = 0xff; + *code |= (type >= SLJIT_FAST_CALL) ? (2 << 3) : (4 << 3); + } + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type) +{ + sljit_ub *buf; + sljit_ub cond_set = 0; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + int reg; +#endif + + CHECK_ERROR(); + check_sljit_emit_cond_value(compiler, op, dst, dstw, type); + + if (dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + CHECK_EXTRA_REGS(dst, dstw, (void)0); + if (SLJIT_UNLIKELY(compiler->flags_saved)) + FAIL_IF(emit_restore_flags(compiler, 0)); + + switch (type) { + case SLJIT_C_EQUAL: + case SLJIT_C_FLOAT_EQUAL: + cond_set = 0x94; + break; + + case SLJIT_C_NOT_EQUAL: + case SLJIT_C_FLOAT_NOT_EQUAL: + cond_set = 0x95; + break; + + case SLJIT_C_LESS: + case SLJIT_C_FLOAT_LESS: + cond_set = 0x92; + break; + + case SLJIT_C_GREATER_EQUAL: + case SLJIT_C_FLOAT_GREATER_EQUAL: + cond_set = 0x93; + break; + + case SLJIT_C_GREATER: + case SLJIT_C_FLOAT_GREATER: + cond_set = 0x97; + break; + + case SLJIT_C_LESS_EQUAL: + case SLJIT_C_FLOAT_LESS_EQUAL: + cond_set = 0x96; + break; + + case SLJIT_C_SIG_LESS: + cond_set = 0x9c; + break; + + case SLJIT_C_SIG_GREATER_EQUAL: + cond_set = 0x9d; + break; + + case SLJIT_C_SIG_GREATER: + cond_set = 0x9f; + break; + + case SLJIT_C_SIG_LESS_EQUAL: + cond_set = 0x9e; + break; + + case SLJIT_C_OVERFLOW: + case SLJIT_C_MUL_OVERFLOW: + cond_set = 0x90; + break; + + case SLJIT_C_NOT_OVERFLOW: + case SLJIT_C_MUL_NOT_OVERFLOW: + cond_set = 0x91; + break; + + case SLJIT_C_FLOAT_NAN: + cond_set = 0x9a; + break; + + case SLJIT_C_FLOAT_NOT_NAN: + cond_set = 0x9b; + break; + } + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + reg = (op == SLJIT_MOV && dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 4 + 4); + FAIL_IF(!buf); + INC_SIZE(4 + 4); + /* Set low register to conditional flag. */ + *buf++ = (reg_map[reg] <= 7) ? 0x40 : REX_B; + *buf++ = 0x0f; + *buf++ = cond_set; + *buf++ = 0xC0 | reg_lmap[reg]; + *buf++ = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R)); + *buf++ = 0x0f; + *buf++ = 0xb6; + *buf = 0xC0 | (reg_lmap[reg] << 3) | reg_lmap[reg]; + + if (reg == TMP_REGISTER) { + if (op == SLJIT_MOV) { + compiler->mode32 = 0; + EMIT_MOV(compiler, dst, dstw, TMP_REGISTER, 0); + } + else { +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0); + } + } +#else + if (op == SLJIT_MOV) { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) { + buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3); + FAIL_IF(!buf); + INC_SIZE(3 + 3); + /* Set low byte to conditional flag. */ + *buf++ = 0x0f; + *buf++ = cond_set; + *buf++ = 0xC0 | reg_map[dst]; + + *buf++ = 0x0f; + *buf++ = 0xb6; + *buf = 0xC0 | (reg_map[dst] << 3) | reg_map[dst]; + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3); + FAIL_IF(!buf); + INC_SIZE(3 + 3); + /* Set al to conditional flag. */ + *buf++ = 0x0f; + *buf++ = cond_set; + *buf++ = 0xC0; + + *buf++ = 0x0f; + *buf++ = 0xb6; + if (dst >= SLJIT_SAVED_REG1 && dst <= SLJIT_NO_REGISTERS) + *buf = 0xC0 | (reg_map[dst] << 3); + else { + *buf = 0xC0; + EMIT_MOV(compiler, dst, dstw, SLJIT_TEMPORARY_REG1, 0); + } + + EMIT_MOV(compiler, SLJIT_TEMPORARY_REG1, 0, TMP_REGISTER, 0); + } + } + else { + if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_TEMPORARY_REG3) { + EMIT_MOV(compiler, TMP_REGISTER, 0, dst, 0); + buf = (sljit_ub*)ensure_buf(compiler, 1 + 3); + FAIL_IF(!buf); + INC_SIZE(3); + + *buf++ = 0x0f; + *buf++ = cond_set; + *buf++ = 0xC0 | reg_map[dst]; + } + else { + EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0); + + buf = (sljit_ub*)ensure_buf(compiler, 1 + 3 + 3 + 1); + FAIL_IF(!buf); + INC_SIZE(3 + 3 + 1); + /* Set al to conditional flag. */ + *buf++ = 0x0f; + *buf++ = cond_set; + *buf++ = 0xC0; + + *buf++ = 0x0f; + *buf++ = 0xb6; + *buf++ = 0xC0; + + *buf++ = 0x90 + reg_map[TMP_REGISTER]; + } +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG) + compiler->skip_checks = 1; +#endif + return sljit_emit_op2(compiler, op, dst, dstw, dst, dstw, TMP_REGISTER, 0); + } +#endif + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value) +{ + sljit_ub *buf; + struct sljit_const *const_; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + int reg; +#endif + + CHECK_ERROR_PTR(); + check_sljit_emit_const(compiler, dst, dstw, init_value); + + CHECK_EXTRA_REGS(dst, dstw, (void)0); + + const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const)); + PTR_FAIL_IF(!const_); + set_const(const_, compiler); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = 0; + reg = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) ? dst : TMP_REGISTER; + + if (emit_load_imm64(compiler, reg, init_value)) + return NULL; +#else + if (dst == SLJIT_UNUSED) + dst = TMP_REGISTER; + + if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value)) + return NULL; +#endif + + buf = (sljit_ub*)ensure_buf(compiler, 2); + PTR_FAIL_IF(!buf); + + *buf++ = 0; + *buf++ = 1; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + if (reg == TMP_REGISTER && dst != SLJIT_UNUSED) + if (emit_mov(compiler, dst, dstw, TMP_REGISTER, 0)) + return NULL; +#endif + + return const_; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) +{ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + *(sljit_w*)addr = new_addr - (addr + 4); +#else + *(sljit_uw*)addr = new_addr; +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant) +{ + *(sljit_w*)addr = new_constant; +} diff --git a/src/3rdparty/pcre/sljit/sljitUtils.c b/src/3rdparty/pcre/sljit/sljitUtils.c new file mode 100644 index 0000000000..98beaa0b5e --- /dev/null +++ b/src/3rdparty/pcre/sljit/sljitUtils.c @@ -0,0 +1,244 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------ */ +/* Locks */ +/* ------------------------------------------------------------------------ */ + +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) + +#ifdef _WIN32 + +#include "windows.h" + +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) + +static HANDLE allocator_mutex = 0; + +static SLJIT_INLINE void allocator_grab_lock(void) +{ + /* No idea what to do if an error occures. Static mutexes should never fail... */ + if (!allocator_mutex) + allocator_mutex = CreateMutex(NULL, TRUE, NULL); + else + WaitForSingleObject(allocator_mutex, INFINITE); +} + +static SLJIT_INLINE void allocator_release_lock(void) +{ + ReleaseMutex(allocator_mutex); +} + +#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ + +#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) + +static HANDLE global_mutex = 0; + +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) +{ + /* No idea what to do if an error occures. Static mutexes should never fail... */ + if (!global_mutex) + global_mutex = CreateMutex(NULL, TRUE, NULL); + else + WaitForSingleObject(global_mutex, INFINITE); +} + +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void) +{ + ReleaseMutex(global_mutex); +} + +#endif /* SLJIT_UTIL_GLOBAL_LOCK */ + +#else /* _WIN32 */ + +#include "pthread.h" + +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) + +static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER; + +static SLJIT_INLINE void allocator_grab_lock(void) +{ + pthread_mutex_lock(&allocator_mutex); +} + +static SLJIT_INLINE void allocator_release_lock(void) +{ + pthread_mutex_unlock(&allocator_mutex); +} + +#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ + +#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) + +static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; + +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void) +{ + pthread_mutex_lock(&global_mutex); +} + +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void) +{ + pthread_mutex_unlock(&global_mutex); +} + +#endif /* SLJIT_UTIL_GLOBAL_LOCK */ + +#endif /* _WIN32 */ + +/* ------------------------------------------------------------------------ */ +/* Stack */ +/* ------------------------------------------------------------------------ */ + +#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) + +#ifdef _WIN32 +#include "windows.h" +#else +#include +#include +#endif + +/* Planning to make it even more clever in the future. */ +static sljit_w sljit_page_align = 0; + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit) +{ + struct sljit_stack *stack; + union { + void *ptr; + sljit_uw uw; + } base; +#ifdef _WIN32 + SYSTEM_INFO si; +#endif + + if (limit > max_limit || limit < 1) + return NULL; + +#ifdef _WIN32 + if (!sljit_page_align) { + GetSystemInfo(&si); + sljit_page_align = si.dwPageSize - 1; + } +#else + if (!sljit_page_align) { + sljit_page_align = sysconf(_SC_PAGESIZE); + /* Should never happen. */ + if (sljit_page_align < 0) + sljit_page_align = 4096; + sljit_page_align--; + } +#endif + + /* Align limit and max_limit. */ + max_limit = (max_limit + sljit_page_align) & ~sljit_page_align; + + stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack)); + if (!stack) + return NULL; + +#ifdef _WIN32 + base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE); + if (!base.ptr) { + SLJIT_FREE(stack); + return NULL; + } + stack->base = base.uw; + stack->limit = stack->base; + stack->max_limit = stack->base + max_limit; + if (sljit_stack_resize(stack, stack->base + limit)) { + sljit_free_stack(stack); + return NULL; + } +#else + base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (base.ptr == MAP_FAILED) { + SLJIT_FREE(stack); + return NULL; + } + stack->base = base.uw; + stack->limit = stack->base + limit; + stack->max_limit = stack->base + max_limit; +#endif + stack->top = stack->base; + return stack; +} + +#undef PAGE_ALIGN + +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* stack) +{ +#ifdef _WIN32 + VirtualFree((void*)stack->base, 0, MEM_RELEASE); +#else + munmap((void*)stack->base, stack->max_limit - stack->base); +#endif + SLJIT_FREE(stack); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit) +{ + sljit_uw aligned_old_limit; + sljit_uw aligned_new_limit; + + if ((new_limit > stack->max_limit) || (new_limit < stack->base)) + return -1; +#ifdef _WIN32 + aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; + aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; + if (aligned_new_limit != aligned_old_limit) { + if (aligned_new_limit > aligned_old_limit) { + if (!VirtualAlloc((void*)aligned_old_limit, aligned_new_limit - aligned_old_limit, MEM_COMMIT, PAGE_READWRITE)) + return -1; + } + else { + if (!VirtualFree((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MEM_DECOMMIT)) + return -1; + } + } + stack->limit = new_limit; + return 0; +#else + if (new_limit >= stack->limit) { + stack->limit = new_limit; + return 0; + } + aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align; + aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align; + if (aligned_new_limit < aligned_old_limit) + madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED); + stack->limit = new_limit; + return 0; +#endif +} + +#endif /* SLJIT_UTIL_STACK */ + +#endif diff --git a/src/3rdparty/pcre/ucp.h b/src/3rdparty/pcre/ucp.h new file mode 100644 index 0000000000..34077fe07e --- /dev/null +++ b/src/3rdparty/pcre/ucp.h @@ -0,0 +1,165 @@ +/************************************************* +* Unicode Property Table handler * +*************************************************/ + +#ifndef _UCP_H +#define _UCP_H + +/* This file contains definitions of the property values that are returned by +the UCD access macros. New values that are added for new releases of Unicode +should always be at the end of each enum, for backwards compatibility. */ + +/* These are the general character categories. */ + +enum { + ucp_C, /* Other */ + ucp_L, /* Letter */ + ucp_M, /* Mark */ + ucp_N, /* Number */ + ucp_P, /* Punctuation */ + ucp_S, /* Symbol */ + ucp_Z /* Separator */ +}; + +/* These are the particular character types. */ + +enum { + ucp_Cc, /* Control */ + ucp_Cf, /* Format */ + ucp_Cn, /* Unassigned */ + ucp_Co, /* Private use */ + ucp_Cs, /* Surrogate */ + ucp_Ll, /* Lower case letter */ + ucp_Lm, /* Modifier letter */ + ucp_Lo, /* Other letter */ + ucp_Lt, /* Title case letter */ + ucp_Lu, /* Upper case letter */ + ucp_Mc, /* Spacing mark */ + ucp_Me, /* Enclosing mark */ + ucp_Mn, /* Non-spacing mark */ + ucp_Nd, /* Decimal number */ + ucp_Nl, /* Letter number */ + ucp_No, /* Other number */ + ucp_Pc, /* Connector punctuation */ + ucp_Pd, /* Dash punctuation */ + ucp_Pe, /* Close punctuation */ + ucp_Pf, /* Final punctuation */ + ucp_Pi, /* Initial punctuation */ + ucp_Po, /* Other punctuation */ + ucp_Ps, /* Open punctuation */ + ucp_Sc, /* Currency symbol */ + ucp_Sk, /* Modifier symbol */ + ucp_Sm, /* Mathematical symbol */ + ucp_So, /* Other symbol */ + ucp_Zl, /* Line separator */ + ucp_Zp, /* Paragraph separator */ + ucp_Zs /* Space separator */ +}; + +/* These are the script identifications. */ + +enum { + ucp_Arabic, + ucp_Armenian, + ucp_Bengali, + ucp_Bopomofo, + ucp_Braille, + ucp_Buginese, + ucp_Buhid, + ucp_Canadian_Aboriginal, + ucp_Cherokee, + ucp_Common, + ucp_Coptic, + ucp_Cypriot, + ucp_Cyrillic, + ucp_Deseret, + ucp_Devanagari, + ucp_Ethiopic, + ucp_Georgian, + ucp_Glagolitic, + ucp_Gothic, + ucp_Greek, + ucp_Gujarati, + ucp_Gurmukhi, + ucp_Han, + ucp_Hangul, + ucp_Hanunoo, + ucp_Hebrew, + ucp_Hiragana, + ucp_Inherited, + ucp_Kannada, + ucp_Katakana, + ucp_Kharoshthi, + ucp_Khmer, + ucp_Lao, + ucp_Latin, + ucp_Limbu, + ucp_Linear_B, + ucp_Malayalam, + ucp_Mongolian, + ucp_Myanmar, + ucp_New_Tai_Lue, + ucp_Ogham, + ucp_Old_Italic, + ucp_Old_Persian, + ucp_Oriya, + ucp_Osmanya, + ucp_Runic, + ucp_Shavian, + ucp_Sinhala, + ucp_Syloti_Nagri, + ucp_Syriac, + ucp_Tagalog, + ucp_Tagbanwa, + ucp_Tai_Le, + ucp_Tamil, + ucp_Telugu, + ucp_Thaana, + ucp_Thai, + ucp_Tibetan, + ucp_Tifinagh, + ucp_Ugaritic, + ucp_Yi, + /* New for Unicode 5.0: */ + ucp_Balinese, + ucp_Cuneiform, + ucp_Nko, + ucp_Phags_Pa, + ucp_Phoenician, + /* New for Unicode 5.1: */ + ucp_Carian, + ucp_Cham, + ucp_Kayah_Li, + ucp_Lepcha, + ucp_Lycian, + ucp_Lydian, + ucp_Ol_Chiki, + ucp_Rejang, + ucp_Saurashtra, + ucp_Sundanese, + ucp_Vai, + /* New for Unicode 5.2: */ + ucp_Avestan, + ucp_Bamum, + ucp_Egyptian_Hieroglyphs, + ucp_Imperial_Aramaic, + ucp_Inscriptional_Pahlavi, + ucp_Inscriptional_Parthian, + ucp_Javanese, + ucp_Kaithi, + ucp_Lisu, + ucp_Meetei_Mayek, + ucp_Old_South_Arabian, + ucp_Old_Turkic, + ucp_Samaritan, + ucp_Tai_Tham, + ucp_Tai_Viet, + /* New for Unicode 6.0.0: */ + ucp_Batak, + ucp_Brahmi, + ucp_Mandaic +}; + +#endif + +/* End of ucp.h */ -- cgit v1.2.3 From 8db8a34f07a2f8cbd06dc0b593886a13d52ae4b1 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 3 Mar 2012 12:53:45 +0100 Subject: Fix documentation of the new connect functions. Make sure that qdoc can find the same function signature in the header than in the \fn tags in qobject.cpp Change-Id: Iccf2ba4e8f6384e9c3bfc878a446120f03e8a813 Reviewed-by: Casper van Donderen --- src/corelib/kernel/qobject.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 5f43b52939..9f09617071 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -198,6 +198,10 @@ public: inline QMetaObject::Connection connect(const QObject *sender, const char *signal, const char *member, Qt::ConnectionType type = Qt::AutoConnection) const; +#ifdef Q_QDOC + QMetaObject::Connection QObject::connect(const QObject *sender, (T::*signal)(...), const QObject *receiver, (T::*method)(...), Qt::ConnectionType type) + QMetaObject::Connection QObject::connect(const QObject *sender, (T::*signal)(...), Functor functor) +#else //Connect a signal to a pointer to qobject member function template static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, @@ -261,6 +265,7 @@ public: new QFunctorSlotObject(slot), Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject); } +#endif //Q_QDOC static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member); @@ -273,6 +278,9 @@ public: { return disconnect(this, 0, receiver, member); } static bool disconnect(const QMetaObject::Connection &); +#ifdef Q_QDOC + bool QObject::disconnect(const QObject *sender, (T::*signal)(...), const Qbject *receiver, (T::*method)(...)) +#else template static inline bool disconnect(const typename QtPrivate::FunctionPointer::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer::Object *receiver, Func2 slot) @@ -300,6 +308,7 @@ public: return disconnectImpl(sender, reinterpret_cast(&signal), receiver, zero, &SignalType::Object::staticMetaObject); } +#endif //Q_QDOC void dumpObjectTree(); -- cgit v1.2.3 From d423fd0975569928faeafad28702750407e889ee Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Mon, 5 Mar 2012 12:10:32 +1000 Subject: Avoid using internal testlib API in QDbusConnection autotest. QCOMPARE should only be used in a test function because it makes the test function return if the compare fails. The test wants to compare without returning on failure because the compare is inside a helper function called by many test functions, so the test was calling testlib's internal QTest::compare_helper() functions instead of QCOMPARE. This commit makes this code slightly less objectionable by calling the public QTest::qCompare() instead. Change-Id: Ida17a641e89f8a297d6a036449f44b33aa266368 Reviewed-by: Thiago Macieira --- .../dbus/qdbusconnection/tst_qdbusconnection.cpp | 24 ++++------------------ 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index e1d128dac7..65b68b7f34 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -829,16 +829,8 @@ bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString QDBusMessage reply = conn.call(msg, QDBus::Block/*WithGui*/); if (reply.type() != QDBusMessage::ReplyMessage) return false; - if (MyObject::path == path) { - QTest::compare_helper(true, "COMPARE()", __FILE__, __LINE__); - } else { - QTest::compare_helper(false, "Compared values are not the same", - QTest::toString(MyObject::path), QTest::toString(path), - "MyObject::path", "path", __FILE__, __LINE__); - return false; - } - - return true; + QTest::qCompare(MyObject::path, path, "MyObject::path", "path", __FILE__, __LINE__); + return (MyObject::path == path); } bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QString &path) @@ -848,16 +840,8 @@ bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QStr if (reply.type() != QDBusMessage::ReplyMessage) return false; - if (MyObject::path == path) { - QTest::compare_helper(true, "COMPARE()", __FILE__, __LINE__); - } else { - QTest::compare_helper(false, "Compared values are not the same", - QTest::toString(MyObject::path), QTest::toString(path), - "MyObject::path", "path", __FILE__, __LINE__); - return false; - } - - return true; + QTest::qCompare(MyObject::path, path, "MyObject::path", "path", __FILE__, __LINE__); + return (MyObject::path == path); } class TestObject : public QObject -- cgit v1.2.3 From 0862d7f78af978cf513097b3bdc33cd8096dee75 Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Thu, 1 Mar 2012 15:14:18 +1000 Subject: testlib: Make verbose2 selftest use QCOMPARE as well as QVERIFY. The verbose output for QCOMPARE is not very helpful. Make the verbose2 selftest (which reuses the counting selftest) demonstrate this, so that a future commit can demonstrate improvement. Change-Id: I6b3bc8f5199e984aa11d0a67b76a8c916be86380 Reviewed-by: Rohan McGovern --- .../testlib/selftests/counting/tst_counting.cpp | 1 + .../testlib/selftests/expected_counting.lightxml | 32 +++++----- tests/auto/testlib/selftests/expected_counting.txt | 32 +++++----- tests/auto/testlib/selftests/expected_counting.xml | 32 +++++----- .../testlib/selftests/expected_verbose1.lightxml | 32 +++++----- tests/auto/testlib/selftests/expected_verbose1.txt | 32 +++++----- tests/auto/testlib/selftests/expected_verbose1.xml | 32 +++++----- .../testlib/selftests/expected_verbose2.lightxml | 68 +++++++++++++++------- tests/auto/testlib/selftests/expected_verbose2.txt | 56 +++++++++++------- tests/auto/testlib/selftests/expected_verbose2.xml | 68 +++++++++++++++------- .../testlib/selftests/expected_verbose2.xunitxml | 14 ++++- 11 files changed, 236 insertions(+), 163 deletions(-) diff --git a/tests/auto/testlib/selftests/counting/tst_counting.cpp b/tests/auto/testlib/selftests/counting/tst_counting.cpp index fa61fce173..9c3dd48015 100644 --- a/tests/auto/testlib/selftests/counting/tst_counting.cpp +++ b/tests/auto/testlib/selftests/counting/tst_counting.cpp @@ -109,6 +109,7 @@ void tst_Counting::helper() switch (result) { case Pass: QVERIFY(true); + QCOMPARE(2 + 1, 3); break; case Fail: QVERIFY(false); diff --git a/tests/auto/testlib/selftests/expected_counting.lightxml b/tests/auto/testlib/selftests/expected_counting.lightxml index e7b1136417..c49792fec4 100644 --- a/tests/auto/testlib/selftests/expected_counting.lightxml +++ b/tests/auto/testlib/selftests/expected_counting.lightxml @@ -17,7 +17,7 @@ - + @@ -26,13 +26,13 @@ - + - + @@ -41,27 +41,27 @@ - + - + - + - + - + @@ -70,21 +70,21 @@ - + - + - + - + @@ -93,7 +93,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -121,7 +121,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_counting.txt b/tests/auto/testlib/selftests/expected_counting.txt index 5c17e3c257..3245d9d7be 100644 --- a/tests/auto/testlib/selftests/expected_counting.txt +++ b/tests/auto/testlib/selftests/expected_counting.txt @@ -5,49 +5,49 @@ PASS : tst_Counting::testPassPass(row 1) PASS : tst_Counting::testPassPass(row 2) PASS : tst_Counting::testPassSkip(row 1) SKIP : tst_Counting::testPassSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] PASS : tst_Counting::testPassFail(row 1) FAIL! : tst_Counting::testPassFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] SKIP : tst_Counting::testSkipPass(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] PASS : tst_Counting::testSkipPass(row 2) SKIP : tst_Counting::testSkipSkip(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] SKIP : tst_Counting::testSkipSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] SKIP : tst_Counting::testSkipFail(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] FAIL! : tst_Counting::testSkipFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailPass(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] PASS : tst_Counting::testFailPass(row 2) FAIL! : tst_Counting::testFailSkip(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] SKIP : tst_Counting::testFailSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] FAIL! : tst_Counting::testFailFail(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] PASS : tst_Counting::testFailInInit(before) FAIL! : tst_Counting::testFailInInit(fail) Fail in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(233)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(234)] PASS : tst_Counting::testFailInInit(after) PASS : tst_Counting::testFailInCleanup(before) QDEBUG : tst_Counting::testFailInCleanup(fail) This test function should execute and then QFAIL in cleanup() FAIL! : tst_Counting::testFailInCleanup(fail) Fail in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(241)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(242)] PASS : tst_Counting::testFailInCleanup(after) PASS : tst_Counting::testSkipInInit(before) SKIP : tst_Counting::testSkipInInit(skip) Skip in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(235)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(236)] PASS : tst_Counting::testSkipInInit(after) PASS : tst_Counting::testSkipInCleanup(before) QDEBUG : tst_Counting::testSkipInCleanup(skip) This test function should execute and then QSKIP in cleanup() SKIP : tst_Counting::testSkipInCleanup(skip) Skip in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(243)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(244)] PASS : tst_Counting::testSkipInCleanup(after) PASS : tst_Counting::cleanupTestCase() Totals: 16 passed, 8 failed, 8 skipped diff --git a/tests/auto/testlib/selftests/expected_counting.xml b/tests/auto/testlib/selftests/expected_counting.xml index a97296807d..7ed93b9c73 100644 --- a/tests/auto/testlib/selftests/expected_counting.xml +++ b/tests/auto/testlib/selftests/expected_counting.xml @@ -19,7 +19,7 @@ - + @@ -28,13 +28,13 @@ - + - + @@ -43,27 +43,27 @@ - + - + - + - + - + @@ -72,21 +72,21 @@ - + - + - + - + @@ -95,7 +95,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -139,7 +139,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_verbose1.lightxml b/tests/auto/testlib/selftests/expected_verbose1.lightxml index e7b1136417..c49792fec4 100644 --- a/tests/auto/testlib/selftests/expected_verbose1.lightxml +++ b/tests/auto/testlib/selftests/expected_verbose1.lightxml @@ -17,7 +17,7 @@ - + @@ -26,13 +26,13 @@ - + - + @@ -41,27 +41,27 @@ - + - + - + - + - + @@ -70,21 +70,21 @@ - + - + - + - + @@ -93,7 +93,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -121,7 +121,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_verbose1.txt b/tests/auto/testlib/selftests/expected_verbose1.txt index 4a0fec51ae..0286f719aa 100644 --- a/tests/auto/testlib/selftests/expected_verbose1.txt +++ b/tests/auto/testlib/selftests/expected_verbose1.txt @@ -8,60 +8,60 @@ PASS : tst_Counting::testPassPass(row 2) INFO : tst_Counting::testPassSkip() entering PASS : tst_Counting::testPassSkip(row 1) SKIP : tst_Counting::testPassSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testPassFail() entering PASS : tst_Counting::testPassFail(row 1) FAIL! : tst_Counting::testPassFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testSkipPass() entering SKIP : tst_Counting::testSkipPass(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] PASS : tst_Counting::testSkipPass(row 2) INFO : tst_Counting::testSkipSkip() entering SKIP : tst_Counting::testSkipSkip(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] SKIP : tst_Counting::testSkipSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testSkipFail() entering SKIP : tst_Counting::testSkipFail(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] FAIL! : tst_Counting::testSkipFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailPass() entering FAIL! : tst_Counting::testFailPass(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] PASS : tst_Counting::testFailPass(row 2) INFO : tst_Counting::testFailSkip() entering FAIL! : tst_Counting::testFailSkip(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] SKIP : tst_Counting::testFailSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testFailFail() entering FAIL! : tst_Counting::testFailFail(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailInInit() entering PASS : tst_Counting::testFailInInit(before) FAIL! : tst_Counting::testFailInInit(fail) Fail in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(233)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(234)] PASS : tst_Counting::testFailInInit(after) INFO : tst_Counting::testFailInCleanup() entering PASS : tst_Counting::testFailInCleanup(before) QDEBUG : tst_Counting::testFailInCleanup(fail) This test function should execute and then QFAIL in cleanup() FAIL! : tst_Counting::testFailInCleanup(fail) Fail in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(241)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(242)] PASS : tst_Counting::testFailInCleanup(after) INFO : tst_Counting::testSkipInInit() entering PASS : tst_Counting::testSkipInInit(before) SKIP : tst_Counting::testSkipInInit(skip) Skip in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(235)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(236)] PASS : tst_Counting::testSkipInInit(after) INFO : tst_Counting::testSkipInCleanup() entering PASS : tst_Counting::testSkipInCleanup(before) QDEBUG : tst_Counting::testSkipInCleanup(skip) This test function should execute and then QSKIP in cleanup() SKIP : tst_Counting::testSkipInCleanup(skip) Skip in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(243)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(244)] PASS : tst_Counting::testSkipInCleanup(after) INFO : tst_Counting::cleanupTestCase() entering PASS : tst_Counting::cleanupTestCase() diff --git a/tests/auto/testlib/selftests/expected_verbose1.xml b/tests/auto/testlib/selftests/expected_verbose1.xml index a97296807d..7ed93b9c73 100644 --- a/tests/auto/testlib/selftests/expected_verbose1.xml +++ b/tests/auto/testlib/selftests/expected_verbose1.xml @@ -19,7 +19,7 @@ - + @@ -28,13 +28,13 @@ - + - + @@ -43,27 +43,27 @@ - + - + - + - + - + @@ -72,21 +72,21 @@ - + - + - + - + @@ -95,7 +95,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -139,7 +139,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_verbose2.lightxml b/tests/auto/testlib/selftests/expected_verbose2.lightxml index b2d9607ade..1310f2bb09 100644 --- a/tests/auto/testlib/selftests/expected_verbose2.lightxml +++ b/tests/auto/testlib/selftests/expected_verbose2.lightxml @@ -10,6 +10,10 @@ + + + + @@ -17,6 +21,10 @@ + + + + @@ -26,10 +34,14 @@ + + + + - + @@ -39,20 +51,24 @@ + + + + - + - + - + @@ -60,40 +76,44 @@ + + + + - + - + - + - + - + - + - + @@ -101,38 +121,42 @@ + + + + - + - + - + - + - + - + - + @@ -141,7 +165,7 @@ - + @@ -157,7 +181,7 @@ - + @@ -169,7 +193,7 @@ - + @@ -185,7 +209,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_verbose2.txt b/tests/auto/testlib/selftests/expected_verbose2.txt index 9d36a5e98e..9012a7c569 100644 --- a/tests/auto/testlib/selftests/expected_verbose2.txt +++ b/tests/auto/testlib/selftests/expected_verbose2.txt @@ -5,87 +5,99 @@ PASS : tst_Counting::initTestCase() INFO : tst_Counting::testPassPass() entering INFO : tst_Counting::testPassPass(row 1) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testPassPass(row 1) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testPassPass(row 1) INFO : tst_Counting::testPassPass(row 2) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testPassPass(row 2) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testPassPass(row 2) INFO : tst_Counting::testPassSkip() entering INFO : tst_Counting::testPassSkip(row 1) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testPassSkip(row 1) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testPassSkip(row 1) SKIP : tst_Counting::testPassSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testPassFail() entering INFO : tst_Counting::testPassFail(row 1) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testPassFail(row 1) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testPassFail(row 1) INFO : tst_Counting::testPassFail(row 2) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testPassFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testSkipPass() entering SKIP : tst_Counting::testSkipPass(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testSkipPass(row 2) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testSkipPass(row 2) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testSkipPass(row 2) INFO : tst_Counting::testSkipSkip() entering SKIP : tst_Counting::testSkipSkip(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] SKIP : tst_Counting::testSkipSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testSkipFail() entering SKIP : tst_Counting::testSkipFail(row 1) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testSkipFail(row 2) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testSkipFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailPass() entering INFO : tst_Counting::testFailPass(row 1) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailPass(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailPass(row 2) QVERIFY(true) Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(111)] +INFO : tst_Counting::testFailPass(row 2) COMPARE() + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(112)] PASS : tst_Counting::testFailPass(row 2) INFO : tst_Counting::testFailSkip() entering INFO : tst_Counting::testFailSkip(row 1) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailSkip(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] SKIP : tst_Counting::testFailSkip(row 2) Skipping - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(117)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(118)] INFO : tst_Counting::testFailFail() entering INFO : tst_Counting::testFailFail(row 1) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailFail(row 1) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailFail(row 2) QVERIFY(false) - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] FAIL! : tst_Counting::testFailFail(row 2) 'false' returned FALSE. () - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(114)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(115)] INFO : tst_Counting::testFailInInit() entering PASS : tst_Counting::testFailInInit(before) FAIL! : tst_Counting::testFailInInit(fail) Fail in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(233)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(234)] PASS : tst_Counting::testFailInInit(after) INFO : tst_Counting::testFailInCleanup() entering PASS : tst_Counting::testFailInCleanup(before) QDEBUG : tst_Counting::testFailInCleanup(fail) This test function should execute and then QFAIL in cleanup() FAIL! : tst_Counting::testFailInCleanup(fail) Fail in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(241)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(242)] PASS : tst_Counting::testFailInCleanup(after) INFO : tst_Counting::testSkipInInit() entering PASS : tst_Counting::testSkipInInit(before) SKIP : tst_Counting::testSkipInInit(skip) Skip in init() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(235)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(236)] PASS : tst_Counting::testSkipInInit(after) INFO : tst_Counting::testSkipInCleanup() entering PASS : tst_Counting::testSkipInCleanup(before) QDEBUG : tst_Counting::testSkipInCleanup(skip) This test function should execute and then QSKIP in cleanup() SKIP : tst_Counting::testSkipInCleanup(skip) Skip in cleanup() - Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(243)] + Loc: [/home/user/dev/qt5/qtbase/tests/auto/testlib/selftests/counting/tst_counting.cpp(244)] PASS : tst_Counting::testSkipInCleanup(after) INFO : tst_Counting::cleanupTestCase() entering PASS : tst_Counting::cleanupTestCase() diff --git a/tests/auto/testlib/selftests/expected_verbose2.xml b/tests/auto/testlib/selftests/expected_verbose2.xml index 90582e6116..693ef2b187 100644 --- a/tests/auto/testlib/selftests/expected_verbose2.xml +++ b/tests/auto/testlib/selftests/expected_verbose2.xml @@ -12,6 +12,10 @@ + + + + @@ -19,6 +23,10 @@ + + + + @@ -28,10 +36,14 @@ + + + + - + @@ -41,20 +53,24 @@ + + + + - + - + - + @@ -62,40 +78,44 @@ + + + + - + - + - + - + - + - + - + @@ -103,38 +123,42 @@ + + + + - + - + - + - + - + - + - + @@ -143,7 +167,7 @@ - + @@ -159,7 +183,7 @@ - + @@ -171,7 +195,7 @@ - + @@ -187,7 +211,7 @@ - + diff --git a/tests/auto/testlib/selftests/expected_verbose2.xunitxml b/tests/auto/testlib/selftests/expected_verbose2.xunitxml index 558550f17b..8b9ed5257d 100644 --- a/tests/auto/testlib/selftests/expected_verbose2.xunitxml +++ b/tests/auto/testlib/selftests/expected_verbose2.xunitxml @@ -1,5 +1,5 @@ - + @@ -7,20 +7,25 @@ + + + + + @@ -35,6 +40,7 @@ + @@ -64,19 +70,25 @@ + + + + + + -- cgit v1.2.3 From 07ae18f96e87a2db40ae014f28893f1080efa7ae Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Fri, 2 Mar 2012 15:42:35 -0800 Subject: Implements QStackedLayout's hfw-related methods. QStackedLayout does not support height for width (simply because it does not reimplement heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking binary compatibility under Qt4, which use a modified version of QStackedLayout that reimplements the hfw-related functions as a workaround. Change-Id: I81c795f0c247a2e708292de35f0650384248c6cd Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qstackedlayout.cpp | 32 +++++++++++++++++++++++ src/widgets/kernel/qstackedlayout.h | 2 ++ src/widgets/widgets/qstackedwidget.cpp | 46 ++-------------------------------- 3 files changed, 36 insertions(+), 44 deletions(-) diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp index 9b40063e65..0d2e7716e5 100644 --- a/src/widgets/kernel/qstackedlayout.cpp +++ b/src/widgets/kernel/qstackedlayout.cpp @@ -476,6 +476,38 @@ void QStackedLayout::setGeometry(const QRect &rect) } } +/*! + \reimp +*/ +bool QStackedLayout::hasHeightForWidth() const +{ + const int n = count(); + + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + if (item->hasHeightForWidth()) + return true; + } + } + return false; +} + +/*! + \reimp +*/ +int QStackedLayout::heightForWidth(int width) const +{ + const int n = count(); + + int hfw = 0; + for (int i = 0; i < n; ++i) { + if (QLayoutItem *item = itemAt(i)) { + hfw = qMax(hfw, item->heightForWidth(width)); + } + } + return hfw; +} + /*! \enum QStackedLayout::StackingMode \since 4.4 diff --git a/src/widgets/kernel/qstackedlayout.h b/src/widgets/kernel/qstackedlayout.h index e54efa886e..fa77341c52 100644 --- a/src/widgets/kernel/qstackedlayout.h +++ b/src/widgets/kernel/qstackedlayout.h @@ -94,6 +94,8 @@ public: QLayoutItem *itemAt(int) const; QLayoutItem *takeAt(int); void setGeometry(const QRect &rect); + bool hasHeightForWidth() const; + int heightForWidth(int width) const; Q_SIGNALS: void widgetRemoved(int index); diff --git a/src/widgets/widgets/qstackedwidget.cpp b/src/widgets/widgets/qstackedwidget.cpp index 5a8a382a58..3c88090eb6 100644 --- a/src/widgets/widgets/qstackedwidget.cpp +++ b/src/widgets/widgets/qstackedwidget.cpp @@ -49,54 +49,12 @@ QT_BEGIN_NAMESPACE -/** - QStackedLayout does not support height for width (simply because it does not reimplement - heightForWidth() and hasHeightForWidth()). That is not possible to fix without breaking - binary compatibility. (QLayout is subject to multiple inheritance). - However, we can fix QStackedWidget by simply using a modified version of QStackedLayout - that reimplements the hfw-related functions: - */ -class QStackedLayoutHFW : public QStackedLayout -{ -public: - QStackedLayoutHFW(QWidget *parent = 0) : QStackedLayout(parent) {} - bool hasHeightForWidth() const; - int heightForWidth(int width) const; -}; - -bool QStackedLayoutHFW::hasHeightForWidth() const -{ - const int n = count(); - - for (int i = 0; i < n; ++i) { - if (QLayoutItem *item = itemAt(i)) { - if (item->hasHeightForWidth()) - return true; - } - } - return false; -} - -int QStackedLayoutHFW::heightForWidth(int width) const -{ - const int n = count(); - - int hfw = 0; - for (int i = 0; i < n; ++i) { - if (QLayoutItem *item = itemAt(i)) { - hfw = qMax(hfw, item->heightForWidth(width)); - } - } - return hfw; -} - - class QStackedWidgetPrivate : public QFramePrivate { Q_DECLARE_PUBLIC(QStackedWidget) public: QStackedWidgetPrivate():layout(0){} - QStackedLayoutHFW *layout; + QStackedLayout *layout; bool blockChildAdd; }; @@ -180,7 +138,7 @@ QStackedWidget::QStackedWidget(QWidget *parent) : QFrame(*new QStackedWidgetPrivate, parent) { Q_D(QStackedWidget); - d->layout = new QStackedLayoutHFW(this); + d->layout = new QStackedLayout(this); connect(d->layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int))); connect(d->layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int))); } -- cgit v1.2.3 From 3ae0164687186b68b530fe8d30f5a3434163c1ee Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 5 Mar 2012 10:52:34 +0200 Subject: Update QTouchEvent docs with regards to raw positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2c955e42605c442793095d5ca27c34d7d87e08fb Reviewed-by: Samuel Rødal --- src/gui/kernel/qevent.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 60e754b289..52cb799b39 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3863,11 +3863,16 @@ QTouchEvent::TouchPoint::InfoFlags QTouchEvent::TouchPoint::flags() const } /*! - Returns the raw, unfiltered positions for the touch point. The positions are in screen coordinates. + Returns the raw, unfiltered positions for the touch point. The positions are in native screen coordinates. To get local coordinates you can use mapFromGlobal() of the QWindow returned by QTouchEvent::window(). \note Returns an empty list if the touch device's capabilities do not include QTouchDevice::RawPositions. + \note Native screen coordinates refer to the native orientation of the screen which, in case of + mobile devices, is typically portrait. This means that on systems capable of screen orientation + changes the positions in this list will not reflect the current orientation (unlike pos(), + screenPos(), etc.) and will always be reported in the native orientation. + \sa QTouchDevice::capabilities(), device(), window() */ QList QTouchEvent::TouchPoint::rawScreenPositions() const -- cgit v1.2.3 From c01ef19e772c3c5dddccf8ea03e7db4e8d71784c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 1 Mar 2012 11:40:49 +0100 Subject: List the dependencies of Qt when creating static libraries. Change-Id: Ib6787f982ff962cfdf3d8a0a26989489619a57b0 Reviewed-by: Clinton Stimpson Reviewed-by: Stephen Kelly --- mkspecs/cmake/Qt5BasicConfig.cmake.in | 55 +++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/mkspecs/cmake/Qt5BasicConfig.cmake.in b/mkspecs/cmake/Qt5BasicConfig.cmake.in index 45a0722ef5..0334b6f6e2 100644 --- a/mkspecs/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/cmake/Qt5BasicConfig.cmake.in @@ -35,6 +35,57 @@ if (Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS) list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS) endif() +!!IF !isEmpty(CMAKE_STATIC_TYPE) +# For static builds, we also list the dependencies of +# Qt so that consumers can build. + +!!IF isEqual(CMAKE_MODULE_NAME, Core) + +set(Qt5Core_LIB_DEPENDENCIES) +!!IF contains(QT_CONFIG, system-zlib) +find_package(ZLIB REQUIRED) +list(APPEND Qt5Core_LIB_DEPENDENCIES ${ZLIB_LIBRARIES}) +!!ENDIF + +!!IF contains(QT_CONFIG, glib) +find_package(GTK2 REQUIRED glib-2.0 gthread-2.0) +list(APPEND Qt5Core_LIB_DEPENDENCIES ${GTK2_LIBRARIES}) +!!ENDIF + +!!IF contains(QT_CONFIG, clock-monotonic) +find_library(QT_RT_LIBRARY NAMES rt) +mark_as_advanced(QT_RT_LIBRARY) +list(APPEND Qt5Core_LIB_DEPENDENCIES ${QT_RT_LIBRARY}) +!!ENDIF + +set(CMAKE_THREAD_PREFER_PTHREADS 1) +find_package(Threads) +if(CMAKE_USE_PTHREADS_INIT) + list(APPEND Qt5Core_LIB_DEPENDENCIES ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS}) +endif() + +!!ENDIF # Core + +!!IF isEqual(CMAKE_MODULE_NAME, Gui) + +set(Qt5Gui_LIB_DEPENDENCIES) + +!!IF contains(QT_CONFIG, system-png) +find_package(PNG REQUIRED) +list(APPEND Qt5Gui_LIB_DEPENDENCIES ${PNG_LIBRARIES}) +!!ENDIF + +!!IF contains(QT_CONFIG, system-jpeg) +find_package(JPEG REQUIRED) +list(APPEND Qt5Gui_LIB_DEPENDENCIES ${JPEG_LIBRARIES}) +!!ENDIF + +!!ENDIF # Gui + +!!ENDIF # Static + +list(APPEND Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES "$${CMAKE_QT5_MODULE_DEPS}") + if (NOT _Qt5$${CMAKE_MODULE_NAME}_target) set(_Qt5$${CMAKE_MODULE_NAME}_target 1) !!IF !isEmpty(CMAKE_STATIC_TYPE) @@ -50,7 +101,7 @@ endif() !!IF !isEmpty(debug_type) set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG \"$${CMAKE_QT5_MODULE_DEPS}\" + IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG \"${Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\" !!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE) IMPORTED_LOCATION_DEBUG \"${_qt5_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_LIB_FILE_LOCATION_DEBUG}\" !!ELSE @@ -67,7 +118,7 @@ set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES !!IF !isEmpty(release_type) set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE \"$${CMAKE_QT5_MODULE_DEPS}\" + IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE \"${Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\" !!IF isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE) IMPORTED_LOCATION_RELEASE \"${_qt5_install_prefix}/$${CMAKE_LIB_DIR}$${CMAKE_LIB_FILE_LOCATION_RELEASE}\" !!ELSE -- cgit v1.2.3 From d94165ab326f24a725720a705405067975b82af8 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 5 Mar 2012 12:31:03 +0100 Subject: Fix tst_QStyleSheetStyle::qproperty to not implicitly rely on QHash ordering. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changing qHash() for string data affected the order of properties to be set, causing 'checkable' to be set after 'checked'. As 'checkable' state affects 'checked' as well (setting it to false), this means that the test was unreliable, a bug, which was exposed by the qHash change. Change-Id: I03a8dd7d07609683d99f0b2a40012a147d409c6e Reviewed-by: Mark Brand Reviewed-by: João Abecasis --- tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 1201b0f1da..8f187190aa 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -555,11 +555,11 @@ void tst_QStyleSheetStyle::layoutSpacing() void tst_QStyleSheetStyle::qproperty() { QPushButton pb; - pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: true; qproperty-checked: 1}"); + pb.setStyleSheet("QPushButton { qproperty-text: hello; qproperty-checkable: 1; qproperty-checked: false}"); pb.ensurePolished(); QCOMPARE(pb.text(), QString("hello")); QCOMPARE(pb.isCheckable(), true); - QCOMPARE(pb.isChecked(), true); + QCOMPARE(pb.isChecked(), false); } namespace ns { -- cgit v1.2.3 From deb3c134b5b718e429a71ed0cff8f1f711b30e62 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 3 Feb 2012 18:03:24 +0100 Subject: remove injection of default_pre in infile()/$$fromfile() this is a hack from the times when these functions were (ab)used to inspect proper project files, but the inclusion was done with a clean project, so that the included files did not have any functions to work with. Change-Id: I19925e8ead597ca38df040000c183e368b32c06d Reviewed-by: Joerg Bornemann --- qmake/project.cpp | 4 ---- .../auto/tools/qmake/testdata/export_across_file_boundaries/oink.pri | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index f6e26254c5..397b4aee18 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1635,10 +1635,6 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash Date: Tue, 21 Feb 2012 22:23:48 +0100 Subject: give load()/include() with target and infile()/$$fromfile() a clean environment load()/include() with a target namespace would inherit the current context. however, if you source a project with all bells and whistles, this makes completely no sense and may be actually counterproductive. infile()/$$fromfile() would have interited only the functions from the current context. that was only a hack to support abusing them. Change-Id: I2e992b923d9e5b0e5056001ca49b35de573abc63 Reviewed-by: Joerg Bornemann --- dist/changes-5.0.0 | 2 ++ qmake/project.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 47994aa774..9644df40a4 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -203,6 +203,8 @@ information about a particular change. - qmake * Projects which explicitly set an empty TARGET are considered broken now. * The makespec and .qmake.cache do not see build pass specific variables any more. + * load()/include() with a target namespace and infile()/$$fromfile() now start with + an entirely pristine context. * Configure's -sysroot and -hostprefix are now handled slightly differently. The QT_INSTALL_... properties are now automatically prefixed with the sysroot; the raw values are available as QT_RAW_INSTALL_... and the sysroot as QT_SYSROOT. diff --git a/qmake/project.cpp b/qmake/project.cpp index 397b4aee18..ecd31d5234 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1633,7 +1633,7 @@ QMakeProject::doProjectInclude(QString file, uchar flags, QHash Date: Mon, 5 Mar 2012 12:01:45 +0100 Subject: Enable name of threads in release mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Naming threads is very useful for release builds. Enabling only on Linux/Mac for now. The Windows port is using debugger specific API for setting thread names, so it has to remain debug mode only. Change-Id: I179521f65f215ff038e8230f958f6aa728ea4cbe Reviewed-by: Lars Knoll Reviewed-by: João Abecasis --- src/corelib/thread/qthread_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index d458ee9472..a0913e5dbc 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -287,7 +287,7 @@ void *QThreadPrivate::start(void *arg) else createEventDispatcher(data); -#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC)) +#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC)) // sets the name of the current thread. QByteArray objectName = thr->objectName().toLocal8Bit(); -- cgit v1.2.3 From 82fd18fe3640a4e4d57cf736691c201e78a4a771 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 1 Mar 2012 15:05:38 +0200 Subject: Windows: Make QSettings autotest significant again The latest windows run of CI has QSettings test passing, so remove the CONFIG += insignificant_test from it. Task-number: QTBUG-24145 Change-Id: I35c0d8d4f72ad49f9f21dcd486ab33a37ab95e15 Reviewed-by: Sergio Ahumada --- tests/auto/corelib/io/qsettings/qsettings.pro | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro index 9de476fe13..1772f4b65f 100644 --- a/tests/auto/corelib/io/qsettings/qsettings.pro +++ b/tests/auto/corelib/io/qsettings/qsettings.pro @@ -5,5 +5,3 @@ SOURCES = tst_qsettings.cpp RESOURCES += qsettings.qrc win32-msvc*:LIBS += advapi32.lib - -win32: CONFIG += insignificant_test # QTBUG-24145 -- cgit v1.2.3 From 79e64ede698bdfa1b21314c445db616db246229b Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 1 Mar 2012 13:18:53 +0100 Subject: Remove #ifdef Q_WS_MAC code from QPrinter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a QPlatformPrinterSupportPlugin on Mac OS X to return the QPrintEngine/QPaintEngine, no need to keep this code. Change-Id: Ie24dcfd157810ede69790fc7b27c12e24766efce Reviewed-by: Morten Johan Sørvig --- src/printsupport/kernel/qprinter.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 447c535420..f56d34975d 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -58,8 +58,6 @@ #if defined (Q_WS_WIN) #include -#elif defined (Q_WS_MAC) -#include #elif defined (QTOPIA_PRINTENGINE) #include #endif @@ -176,11 +174,6 @@ void QPrinterPrivate::createDefaultEngines() paintEngine = pdfEngine; printEngine = pdfEngine; } -#if defined (Q_WS_MAC) - QMacPrintEngine *macEngine = new QMacPrintEngine(printerMode); - paintEngine = macEngine; - printEngine = macEngine; -#endif } break; case QPrinter::PdfFormat: { -- cgit v1.2.3 From 0cb58c7c6d0143b3ebb7527fccf74c750b9e32be Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 1 Mar 2012 13:19:15 +0100 Subject: Replace Q_WS_MAC with Q_OS_MAC in QtPrintSupport Change-Id: Ib19c87a72f74e28412a6060a83bf17d1d16a83ac Reviewed-by: John Layt --- src/printsupport/dialogs/qprintpreviewdialog.cpp | 6 +++--- src/printsupport/widgets/qprintpreviewwidget.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp index c7b450786d..ce2362b4fe 100644 --- a/src/printsupport/dialogs/qprintpreviewdialog.cpp +++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp @@ -271,7 +271,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) QWidget *pageEdit = new QWidget(toolbar); QVBoxLayout *vboxLayout = new QVBoxLayout; vboxLayout->setContentsMargins(0, 0, 0, 0); -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC // We query the widgets about their size and then we fix the size. // This should do the trick for the laying out part... QSize pageNumEditSize, pageNumLabelSize; @@ -281,7 +281,7 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer) pageNumLabel->resize(pageNumLabelSize); #endif QFormLayout *formLayout = new QFormLayout; -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC // We have to change the growth policy in Mac. formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); #endif @@ -560,7 +560,7 @@ void QPrintPreviewDialogPrivate::_q_print() { Q_Q(QPrintPreviewDialog); -#if defined(Q_OS_WIN) || defined(Q_WS_MAC) +#if defined(Q_OS_WIN) || defined(Q_OS_MAC) if (printer->outputFormat() != QPrinter::NativeFormat) { QString title; QString suffix; diff --git a/src/printsupport/widgets/qprintpreviewwidget.cpp b/src/printsupport/widgets/qprintpreviewwidget.cpp index 16aea238b1..abed05292e 100644 --- a/src/printsupport/widgets/qprintpreviewwidget.cpp +++ b/src/printsupport/widgets/qprintpreviewwidget.cpp @@ -152,7 +152,7 @@ public: GraphicsView(QWidget* parent = 0) : QGraphicsView(parent) { -#ifdef Q_WS_MAC +#ifdef Q_OS_MAC setFrameStyle(QFrame::NoFrame); #endif } -- cgit v1.2.3 From e1ec8727ea94153ebdf2b06184de20901f1facb9 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 1 Mar 2012 08:22:57 +0100 Subject: Add API to convert QSizeF<->PaperSize in QPlatformPrinterSupport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These static public functions give printsupport plugins access to the non-exported qt_paperSizeToQSizeF() and qSizeFTopaperSize() functions in qprinter.cpp to aid implementing QPrintEngine and QPlatformPrinterSupport::supportedPaperSizes(). Change-Id: I3ebcdcd17e863b06ceb135e096e630b37882a293 Reviewed-by: Morten Johan Sørvig --- .../kernel/qplatformprintersupport_qpa.cpp | 20 ++++++++++++++++++++ .../kernel/qplatformprintersupport_qpa.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.cpp b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp index aeb4599955..b6f65ee893 100644 --- a/src/printsupport/kernel/qplatformprintersupport_qpa.cpp +++ b/src/printsupport/kernel/qplatformprintersupport_qpa.cpp @@ -124,6 +124,26 @@ void QPlatformPrinterSupport::setPrinterInfoCupsPrinterIndex(QPrinterInfo *p, in #endif } +/* + Converts QSizeF in millimeters to a predefined PaperSize (returns Custom if + the size isn't a standard size) +*/ +QPrinter::PaperSize QPlatformPrinterSupport::convertQSizeFToPaperSize(const QSizeF &sizef) +{ + extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF &); + return qSizeFTopaperSize(sizef); +} + +/* + Converts a predefined PaperSize to a QSizeF in millimeters (returns + QSizeF(0.0, 0.0) if PaperSize is Custom) +*/ +QSizeF QPlatformPrinterSupport::convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize) +{ + extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size); + return qt_paperSizeToQSizeF(paperSize); +} + QT_END_NAMESPACE #endif // QT_NO_PRINTER diff --git a/src/printsupport/kernel/qplatformprintersupport_qpa.h b/src/printsupport/kernel/qplatformprintersupport_qpa.h index 53f5900cce..5dba56579c 100644 --- a/src/printsupport/kernel/qplatformprintersupport_qpa.h +++ b/src/printsupport/kernel/qplatformprintersupport_qpa.h @@ -66,6 +66,9 @@ public: virtual QList availablePrinters(); virtual QPrinterInfo defaultPrinter(); + static QPrinter::PaperSize convertQSizeFToPaperSize(const QSizeF &sizef); + static QSizeF convertPaperSizeToQSizeF(QPrinter::PaperSize paperSize); + protected: static QPrinterInfo printerInfo(const QString &printerName, bool isDefault = false); static void setPrinterInfoDefault(QPrinterInfo *p, bool isDefault); -- cgit v1.2.3 From b7ba68515023995e998039d92780dded8bbfd325 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 2 Mar 2012 11:10:23 +0100 Subject: Don't leak from QPlatformPrinterSupportPlugin::get() Cache the first QPlatformPrinterSupport returned from the first QPlatformPrinterSupportPlugin, and treat it as an persistent singelton. Change-Id: Ic1c83d7c1cdf4a09723a74e0b9fd485e0b0b3acb Reviewed-by: Lars Knoll --- src/printsupport/kernel/qplatformprintplugin.cpp | 26 +++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/printsupport/kernel/qplatformprintplugin.cpp b/src/printsupport/kernel/qplatformprintplugin.cpp index 409de3eb4a..2c87fcc5e6 100644 --- a/src/printsupport/kernel/qplatformprintplugin.cpp +++ b/src/printsupport/kernel/qplatformprintplugin.cpp @@ -58,15 +58,27 @@ QPlatformPrinterSupportPlugin::~QPlatformPrinterSupportPlugin() { } +/*! + \internal + + Returns a lazily-initialized singleton. Ownership is granted to the + QPlatformPrinterSupportPlugin, which is never unloaded or destroyed until + application exit, i.e. you can expect this pointer to always be valid and + multiple calls to this function will always return the same pointer. +*/ QPlatformPrinterSupport *QPlatformPrinterSupportPlugin::get() { - QStringList k = loader()->keys(); - if (k.isEmpty()) - return 0; - QPlatformPrinterSupportPlugin *plugin = qobject_cast(loader()->instance(k.first())); - if (!plugin) - return 0; - return plugin->create(k.first()); + static QPlatformPrinterSupport *singleton = 0; + if (!singleton) { + QStringList k = loader()->keys(); + if (k.isEmpty()) + return 0; + QPlatformPrinterSupportPlugin *plugin = qobject_cast(loader()->instance(k.first())); + if (!plugin) + return 0; + singleton = plugin->create(k.first()); + } + return singleton; } QT_END_NAMESPACE -- cgit v1.2.3 From f449cefc27fc321f96aadbcb0f0a46e6f7a2b0b4 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Sun, 12 Feb 2012 12:35:12 +0100 Subject: Remove AccessibilityPrepare event. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This event was completely unused. In addition it leads to crashes on linux when sending the Destroy accessibility update. The Destroy event on linux would still query an accessible interface. That in turn would trigger the event to be sent. Change-Id: I8915527de067b8b70ba41b1361e3ef5d12866d7d Reviewed-by: Frederik Gladhorn Reviewed-by: Jan-Arve Sæther --- src/corelib/kernel/qcoreevent.h | 1 - src/gui/accessible/qaccessible.cpp | 4 ---- src/widgets/kernel/qapplication.cpp | 1 - src/widgets/statemachine/qguistatemachine.cpp | 2 -- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 7 ------- 5 files changed, 15 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index cac89f2b13..1d54b32dfa 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -127,7 +127,6 @@ public: DeactivateControl = 81, // ActiveX deactivation ContextMenu = 82, // context popup menu InputMethod = 83, // input method - AccessibilityPrepare = 86, // accessibility information is requested TabletMove = 87, // Wacom tablet event LocaleChange = 88, // the system locale changed LanguageChange = 89, // the application language changed diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index aa47616161..e5b290ae1f 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -571,10 +571,6 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) if (!object) return 0; - QEvent e(QEvent::AccessibilityPrepare); - - QCoreApplication::sendEvent(object, &e); - const QMetaObject *mo = object->metaObject(); while (mo) { const QLatin1String cn(mo->className()); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 095b58eeaf..53f4942310 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3124,7 +3124,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) case QEvent::ChildRemoved: case QEvent::UpdateRequest: case QEvent::UpdateLater: - case QEvent::AccessibilityPrepare: case QEvent::LocaleChange: case QEvent::Style: case QEvent::IconDrag: diff --git a/src/widgets/statemachine/qguistatemachine.cpp b/src/widgets/statemachine/qguistatemachine.cpp index 465da1e2ba..7c8de05466 100644 --- a/src/widgets/statemachine/qguistatemachine.cpp +++ b/src/widgets/statemachine/qguistatemachine.cpp @@ -181,8 +181,6 @@ static QEvent *cloneEvent(QEvent *e) #endif case QEvent::InputMethod: return new QInputMethodEvent(*static_cast(e)); - case QEvent::AccessibilityPrepare: - return new QEvent(*e); case QEvent::LocaleChange: return new QEvent(*e); case QEvent::LanguageChange: diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index caf0f1f80d..dab9dd7690 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -5693,7 +5693,6 @@ private: void tst_QWidget::childEvents() { EventRecorder::EventList expected; - bool accessibilityEnabled = false; // Move away the cursor; otherwise it might result in an enter event if it's // inside the widget when the widget is shown. @@ -5735,8 +5734,6 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); - if (accessibilityEnabled) - expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); @@ -5820,8 +5817,6 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); - if (accessibilityEnabled) - expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); @@ -5908,8 +5903,6 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show); - if (accessibilityEnabled) - expected << qMakePair(&widget, QEvent::AccessibilityPrepare); expected << qMakePair(&widget, QEvent::ShowToParent); QCOMPARE(spy.eventList(), expected); spy.clear(); -- cgit v1.2.3 From 961c3f958f2cd4c993fc384c6e50e25e080c7585 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 6 Mar 2012 09:48:59 +1000 Subject: Stabilize tst_QAccessibility::actionTest show() on a window is asynchronous. Wait for it to complete before continuing with the test. Change-Id: Icd0daa0c0e8f287171c57708bb2fce0b6cf0906a Reviewed-by: Toby Tomkins Reviewed-by: Kalle Lehtonen --- tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index b2a4b1cca2..4c370bebc7 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -777,6 +777,7 @@ void tst_QAccessibility::actionTest() { QPushButton *button = new QPushButton; button->show(); + QTest::qWaitForWindowShown(button); button->clearFocus(); QCOMPARE(button->hasFocus(), false); QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button); -- cgit v1.2.3 From 443fd332f941f8c30074390ddd9e00ee40cd584d Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 6 Mar 2012 09:54:55 +1000 Subject: Stabilize tst_QShortcut show() on a window is asynchronous. Wait for it to complete before continuing with the test. Note the test already contained code for this, but it was inside of a Q_WS_X11 block, making it dead code in Qt 5. Change-Id: I06f892eea86278c56b1773a7e968bbe065f86260 Reviewed-by: Kalle Lehtonen --- tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp index 97c749e5ba..7a87266b8b 100644 --- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp @@ -221,9 +221,7 @@ void tst_QShortcut::initTestCase() mainW->setFixedSize( 100, 100 ); mainW->setCentralWidget( edit ); mainW->show(); -#ifdef Q_WS_X11 - qt_x11_wait_for_window_manager(mainW); -#endif + QTest::qWaitForWindowShown(mainW); mainW->activateWindow(); QTest::qWait(100); connect( mainW->statusBar(), SIGNAL(messageChanged(const QString&)), -- cgit v1.2.3 From 7206f9c539f7302b7349be111e9400c3abb7b048 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 6 Mar 2012 10:03:35 +1000 Subject: Stabilize tst_QCalendarWidget::buttonClickCheck The window should be shown and activated before sending user input. Task-number: QTBUG-23615 Change-Id: I2fc1738d9dc4ee7f03c81b040eed6389910a9d3c Reviewed-by: Toby Tomkins --- tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro | 3 --- tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro index 127d78596a..f16110cbd1 100644 --- a/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro +++ b/tests/auto/widgets/widgets/qcalendarwidget/qcalendarwidget.pro @@ -2,6 +2,3 @@ CONFIG += testcase TARGET = tst_qcalendarwidget QT += widgets testlib SOURCES += tst_qcalendarwidget.cpp - -# QTBUG-23615 - unstable test -linux-*:system(". /etc/lsb-release && [ $DISTRIB_CODENAME = oneiric ]"):CONFIG += insignificant_test diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp index 4f95f80525..4857900dc8 100644 --- a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp +++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp @@ -175,6 +175,8 @@ void tst_QCalendarWidget::buttonClickCheck() QSize size = object.sizeHint(); object.setGeometry(0,0,size.width(), size.height()); object.show(); + QTest::qWaitForWindowShown(&object); + object.activateWindow(); QDate selectedDate(2005, 1, 1); //click on the month buttons -- cgit v1.2.3 From 50ca45f0595242937908854cd37428c397b9cf60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 5 Mar 2012 11:04:48 +0100 Subject: Worked around Metacity crashes in xcb plugin. Setting the user time before mapping the window seems to prevent the crasher from happening. We used to set the user time before mapping in Qt 4.8 too, so it's probably the right thing to do. Task-number: QTBUG-24462 Change-Id: Ia670b799bd1ed7a7e6399631d5242e57324918b3 Reviewed-by: Jan Arne Petersen Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 739426a92a..542d7ab69f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -548,6 +548,8 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } + updateNetWmUserTime(connection()->time()); + Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); xcb_flush(xcb_connection()); -- cgit v1.2.3 From 50f6cf6e4852ff39a79bde074204b498ee9ce21d Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 14 Feb 2012 16:51:20 +0100 Subject: QSqlTableModel: remove unnecessary parameter from setSubmitted() Change-Id: I6d23788163ffd6ba7a8f01ed40910d861ff92703 Reviewed-by: Honglei Zhang --- src/sql/models/qsqltablemodel.cpp | 2 +- src/sql/models/qsqltablemodel_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 571c28f515..075e32ff6e 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -684,7 +684,7 @@ bool QSqlTableModel::submitAll() Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation"); break; } - it.value().setSubmitted(true); + it.value().setSubmitted(); } return select(); diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index 0ae6b53742..168b689441 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -115,7 +115,7 @@ public: m_rec.setGenerated(c, true); } inline bool submitted() const { return m_submitted; } - inline void setSubmitted(bool b) { m_submitted = b; } + inline void setSubmitted() { m_submitted = true; } private: Op m_op; QSqlRecord m_rec; -- cgit v1.2.3 From 463bd32fe5120d3954d93b6792050ac47796467f Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 14 Feb 2012 22:50:40 +0100 Subject: QSqlTableModel: mirror database values in change cache Between submitting and the next select, these values will be more up-to-date than those that could be obtained from the query. This will be useful for constructing primary values and reverting changes made after submitting. Change-Id: I8317617f3e7043ad0b79b333731c55fb88aef171 Reviewed-by: Honglei Zhang --- src/sql/models/qsqltablemodel.cpp | 6 +++--- src/sql/models/qsqltablemodel_p.h | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 075e32ff6e..d31e4bc335 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -510,7 +510,7 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in if (row.op() == QSqlTableModelPrivate::None) row = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update, - d->rec); + record(index.row())); row.setValue(index.column(), value); emit dataChanged(index, index); @@ -1004,7 +1004,7 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) // so fake this by adjusting row --row; } else { - d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete); + d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx)); if (d->strategy == OnManualSubmit) emit headerDataChanged(Qt::Vertical, idx, idx); } @@ -1235,7 +1235,7 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values) QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row]; if (mrow.op() == QSqlTableModelPrivate::None) mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Update, - d->rec); + record(row)); Map::const_iterator i = map.constBegin(); const Map::const_iterator e = map.constEnd(); diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index 168b689441..7266810c40 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -102,10 +102,7 @@ public: public: inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord()) : m_op(o), m_rec(r), m_submitted(false) - { - for (int i = m_rec.count() - 1; i >= 0; --i) - m_rec.setGenerated(i, false); - } + { init_rec(); } inline Op op() const { return m_op; } inline QSqlRecord rec() const { return m_rec; } inline QSqlRecord& recRef() { return m_rec; } @@ -117,8 +114,15 @@ public: inline bool submitted() const { return m_submitted; } inline void setSubmitted() { m_submitted = true; } private: + void init_rec() + { + for (int i = m_rec.count() - 1; i >= 0; --i) + m_rec.setGenerated(i, false); + m_db_values = m_rec; + } Op m_op; QSqlRecord m_rec; + QSqlRecord m_db_values; bool m_submitted; }; -- cgit v1.2.3 From 698e620aad68d702c32b62e8114fe12a7b3e2ca5 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 14 Feb 2012 23:45:44 +0100 Subject: QSqlTableModel: derive primary values from database values Primary values are used to map a row in the model to a row in the database table. It is critically important between submitting a change and the following select (which refreshes the query) to have updated primary values. Otherwise, if the change affected the primary values, additional changes before select will misbehave. Change-Id: I5d08dd70ac5d3f06cd9d3186a439f4c80a037c2d Reviewed-by: Yunqiao Yin --- src/sql/models/qsqltablemodel.cpp | 11 +---------- src/sql/models/qsqltablemodel_p.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index d31e4bc335..a2999b30c4 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -201,16 +201,7 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement, QSqlRecord QSqlTableModelPrivate::primaryValues(int row) const { - Q_Q(const QSqlTableModel); - if (cache.value(row).op() == Insert) - return QSqlRecord(); - - QSqlRecord values(primaryIndex.isEmpty() ? rec : primaryIndex); - - for (int i = 0; i < values.count(); ++i) - values.setValue(i, q->QSqlQueryModel::data(createIndex(row, rec.indexOf(values.fieldName(i))), Qt::EditRole)); - - return values; + return cache.value(row).primaryValues(primaryIndex.isEmpty() ? rec : primaryIndex); } /*! diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index 7266810c40..57051a0e9c 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -113,6 +113,18 @@ public: } inline bool submitted() const { return m_submitted; } inline void setSubmitted() { m_submitted = true; } + inline QSqlRecord primaryValues(const QSqlRecord& pi) const + { + if (m_op == None || m_op == Insert) + return QSqlRecord(); + + QSqlRecord values(pi); + + for (int i = values.count() - 1; i >= 0; --i) + values.setValue(i, m_db_values.value(values.fieldName(i))); + + return values; + } private: void init_rec() { -- cgit v1.2.3 From e999ca25c66dfb9d056a1a83b93043ece5733d93 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 15 Feb 2012 11:23:54 +0100 Subject: add strategy support to sqlbrowser example Several useful options added to context menu. Also added yellow background for unsubmitted changes. Change-Id: I132cd4498a5fb7275ea10c0497910aba99c06a2b Reviewed-by: Honglei Zhang Reviewed-by: Yunqiao Yin --- examples/sql/sqlbrowser/browser.cpp | 75 +++++++++++-- examples/sql/sqlbrowser/browser.h | 20 ++++ examples/sql/sqlbrowser/browserwidget.ui | 184 +++++++++++++++++++------------ 3 files changed, 200 insertions(+), 79 deletions(-) diff --git a/examples/sql/sqlbrowser/browser.cpp b/examples/sql/sqlbrowser/browser.cpp index 3aa330e227..eaaec25b16 100644 --- a/examples/sql/sqlbrowser/browser.cpp +++ b/examples/sql/sqlbrowser/browser.cpp @@ -52,6 +52,12 @@ Browser::Browser(QWidget *parent) table->addAction(insertRowAction); table->addAction(deleteRowAction); + table->addAction(fieldStrategyAction); + table->addAction(rowStrategyAction); + table->addAction(manualStrategyAction); + table->addAction(submitAction); + table->addAction(revertAction); + table->addAction(selectAction); if (QSqlDatabase::drivers().isEmpty()) QMessageBox::information(this, tr("No database drivers found"), @@ -144,7 +150,7 @@ void Browser::addConnection() void Browser::showTable(const QString &t) { - QSqlTableModel *model = new QSqlTableModel(table, connectionWidget->currentDatabase()); + QSqlTableModel *model = new CustomModel(table, connectionWidget->currentDatabase()); model->setEditStrategy(QSqlTableModel::OnRowChange); model->setTable(connectionWidget->currentDatabase().driver()->escapeIdentifier(t, QSqlDriver::TableName)); model->select(); @@ -215,8 +221,6 @@ void Browser::deleteRow() if (!model) return; - model->setEditStrategy(QSqlTableModel::OnManualSubmit); - QModelIndexList currentSelection = table->selectionModel()->selectedIndexes(); for (int i = 0; i < currentSelection.count(); ++i) { if (currentSelection.at(i).column() != 0) @@ -224,24 +228,79 @@ void Browser::deleteRow() model->removeRow(currentSelection.at(i).row()); } - model->submitAll(); - model->setEditStrategy(QSqlTableModel::OnRowChange); - updateActions(); } void Browser::updateActions() { - bool enableIns = qobject_cast(table->model()); + QSqlTableModel * tm = qobject_cast(table->model()); + bool enableIns = tm; bool enableDel = enableIns && table->currentIndex().isValid(); insertRowAction->setEnabled(enableIns); deleteRowAction->setEnabled(enableDel); + + fieldStrategyAction->setEnabled(tm); + rowStrategyAction->setEnabled(tm); + manualStrategyAction->setEnabled(tm); + submitAction->setEnabled(tm); + revertAction->setEnabled(tm); + selectAction->setEnabled(tm); + + if (tm) { + QSqlTableModel::EditStrategy es = tm->editStrategy(); + fieldStrategyAction->setChecked(es == QSqlTableModel::OnFieldChange); + rowStrategyAction->setChecked(es == QSqlTableModel::OnRowChange); + manualStrategyAction->setChecked(es == QSqlTableModel::OnManualSubmit); + } } void Browser::about() { QMessageBox::about(this, tr("About"), tr("The SQL Browser demonstration " "shows how a data browser can be used to visualize the results of SQL" - "statements on a live database")); + "statements on a live database")); +} + +void Browser::on_fieldStrategyAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->setEditStrategy(QSqlTableModel::OnFieldChange); +} + +void Browser::on_rowStrategyAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->setEditStrategy(QSqlTableModel::OnRowChange); +} + +void Browser::on_manualStrategyAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->setEditStrategy(QSqlTableModel::OnManualSubmit); +} + +void Browser::on_submitAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->submitAll(); +} + +void Browser::on_revertAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->revertAll(); +} + +void Browser::on_selectAction_triggered() +{ + QSqlTableModel * tm = qobject_cast(table->model()); + if (tm) + tm->select(); } + diff --git a/examples/sql/sqlbrowser/browser.h b/examples/sql/sqlbrowser/browser.h index 0769812ec8..e9f45345df 100644 --- a/examples/sql/sqlbrowser/browser.h +++ b/examples/sql/sqlbrowser/browser.h @@ -43,6 +43,7 @@ #define BROWSER_H #include +#include #include "ui_browserwidget.h" class ConnectionWidget; @@ -77,6 +78,12 @@ public slots: { insertRow(); } void on_deleteRowAction_triggered() { deleteRow(); } + void on_fieldStrategyAction_triggered(); + void on_rowStrategyAction_triggered(); + void on_manualStrategyAction_triggered(); + void on_submitAction_triggered(); + void on_revertAction_triggered(); + void on_selectAction_triggered(); void on_connectionWidget_tableActivated(const QString &table) { showTable(table); } void on_connectionWidget_metaDataRequested(const QString &table) @@ -96,4 +103,17 @@ signals: void statusMessage(const QString &message); }; +class CustomModel: public QSqlTableModel +{ + Q_OBJECT +public: + CustomModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase()):QSqlTableModel(parent, db) {} + QVariant data(const QModelIndex &idx, int role) const + { + if (role == Qt::BackgroundRole && isDirty(idx)) + return QBrush(QColor(Qt::yellow)); + return QSqlTableModel::data(idx, role); + } +}; + #endif diff --git a/examples/sql/sqlbrowser/browserwidget.ui b/examples/sql/sqlbrowser/browserwidget.ui index 20946f0ede..ff65b1f199 100644 --- a/examples/sql/sqlbrowser/browserwidget.ui +++ b/examples/sql/sqlbrowser/browserwidget.ui @@ -1,10 +1,8 @@ - - - - + + Browser - - + + 0 0 @@ -12,100 +10,90 @@ 515 - + Qt SQL Browser - - - 8 - - + + 6 + + 8 + - - - - 7 - 7 + + + 0 0 - + Qt::Horizontal - - - - 13 - 7 + + + 1 0 - - - - 7 - 7 + + + 2 0 - + Qt::ActionsContextMenu - + QAbstractItemView::SelectRows - - - - 5 - 3 + + + 0 0 - + 16777215 180 - + SQL Query - - - 9 - - + + 6 + + 9 + - - - - 7 - 3 + + + 0 0 - + 0 18 - + 0 120 @@ -114,19 +102,19 @@ - - - 1 - - + + 6 + + 1 + - + Qt::Horizontal - + 40 20 @@ -135,15 +123,15 @@ - - + + &Clear - - + + &Submit @@ -154,37 +142,91 @@ - - + + false - + &Insert Row - + Inserts a new Row - - + + false - + &Delete Row - + Deletes the current Row + + + true + + + Submit on &Field Change + + + Commit on Field Change + + + + + true + + + Submit on &Row Change + + + Commit on Row Change + + + + + true + + + Submit &Manually + + + Commit Manually + + + + + &Submit All + + + Submit Changes + + + + + &Revert All + + + Revert + + + + + S&elect + + + Refresh Data from Database + + - ConnectionWidget QTreeView
connectionwidget.h
- 0 -
-- cgit v1.2.3 From ea6d1fde1b5ce53691cc9b9154bd992a16be035f Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 15 Feb 2012 02:07:59 +0100 Subject: QSqlTableModel::data(): use cached values when available Simplify logic. If the record is in the cache, even untouched values should be there. This is also necessary for getting the most up-to-date values between submitting and the next select. Change-Id: I8578d96229797ce9fb0d07fe456301358f2be071 Reviewed-by: Honglei Zhang --- src/sql/models/qsqltablemodel.cpp | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index a2999b30c4..24668dd946 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -402,29 +402,9 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole)) return QVariant(); - if (d->cache.contains(index.row())) { - const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row()); - - switch (d->strategy) { - case OnFieldChange: - case OnRowChange: - if (row.op() == QSqlTableModelPrivate::Insert) { - if (index.column() < 0 || index.column() >= row.rec().count()) - return QVariant(); - return row.rec().value(index.column()); - } else if (row.op() == QSqlTableModelPrivate::Update) { - if (row.rec().isGenerated(index.column())) - return row.rec().value(index.column()); - } - break; - case OnManualSubmit: - if (row.op() == QSqlTableModelPrivate::Insert - || (row.op() != QSqlTableModelPrivate::None - && row.rec().isGenerated(index.column()))) - return row.rec().value(index.column()); - break; - } - } + const QSqlTableModelPrivate::ModifiedRow mrow = d->cache.value(index.row()); + if (mrow.op() != QSqlTableModelPrivate::None) + return mrow.rec().value(index.column()); return QSqlQueryModel::data(index, role); } -- cgit v1.2.3 From eb150a51cd1e439fd719fe3cd3f30c53f9a1348a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 5 Mar 2012 22:11:05 +0100 Subject: Remove unused QThreadPoolPrivate::startFrontRunnable(). Change-Id: Ie079aea3412a53cf9dccaa770fa64ff5b6b7b3b1 Reviewed-by: Stephen Kelly --- src/corelib/thread/qthreadpool.cpp | 25 ------------------------- src/corelib/thread/qthreadpool_p.h | 1 - 2 files changed, 26 deletions(-) diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index af8c99197e..b7021817c5 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -307,31 +307,6 @@ bool QThreadPoolPrivate::waitForDone(int msecs) return queue.isEmpty() && activeThreads == 0; } -/*! \internal - Pulls a runnable from the front queue and runs it in the current thread. Blocks - until the runnable has completed. Returns true if a runnable was found. -*/ -bool QThreadPoolPrivate::startFrontRunnable() -{ - QMutexLocker locker(&mutex); - if (queue.isEmpty()) - return false; - - QRunnable *runnable = queue.takeFirst().first; - const bool autoDelete = runnable->autoDelete(); - bool del = autoDelete && !--runnable->ref; - - locker.unlock(); - runnable->run(); - locker.relock(); - - if (del) { - delete runnable; - } - - return true; -} - /*! \internal Seaches for \a runnable in the queue, removes it from the queue and runs it if found. This functon does not return until the runnable diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index 9a7c09695f..910e0b0714 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -83,7 +83,6 @@ public: void startThread(QRunnable *runnable = 0); void reset(); bool waitForDone(int msecs = -1); - bool startFrontRunnable(); void stealRunnable(QRunnable *); mutable QMutex mutex; -- cgit v1.2.3 From 95550c8f1292c93ea42d59283394fc4f4d63bf2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Mon, 5 Mar 2012 15:27:40 +0100 Subject: Mark QMetaType constructor as explicit. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implicit conversion from an int would look strange in this case. Change-Id: I2222a045c293595d7b83a2fb75ca646f5cf79bca Reviewed-by: Stephen Kelly Reviewed-by: João Abecasis --- src/corelib/kernel/qmetatype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index f969875455..7f6eaf2230 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -255,7 +255,7 @@ public: static bool load(QDataStream &stream, int type, void *data); #endif - QMetaType(const int type); + explicit QMetaType(const int type); inline ~QMetaType(); inline bool isValid() const; -- cgit v1.2.3 From 9c75d0a91327868b2131d11caea2cd0ccd437711 Mon Sep 17 00:00:00 2001 From: Alex Wilson Date: Mon, 5 Mar 2012 18:16:58 +1000 Subject: Support new-style plugins without a "Keys" json property As per discussion with Lars, intent here was to allow plugins without a "Keys" property to still function correctly, but this particular if statement was blocking any such plugins from being detected. Change-Id: Icb343ca8bd95a508d62565cd816fe2a57a4f82bd Reviewed-by: Lars Knoll --- src/corelib/plugin/qfactoryloader.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 566ece77c9..cdc72cf35d 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -128,6 +128,7 @@ void QFactoryLoader::update() QLibraryPrivate *library = 0; for (int j = 0; j < plugins.count(); ++j) { QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j)); + if (qt_debug_component()) { qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; } @@ -140,7 +141,9 @@ void QFactoryLoader::update() library->release(); continue; } + QStringList keys; + bool metaDataOk = false; if (library->compatPlugin) { qWarning("Qt plugin loader: Compatibility plugin '%s', need to load for accessing meta data.", qPrintable(QDir::toNativeSeparators(fileName))); @@ -164,10 +167,17 @@ void QFactoryLoader::update() QFactoryInterface *factory = qobject_cast(instance); if (instance && factory && instance->qt_metacast(d->iid)) keys = factory->keys(); + + if (!keys.isEmpty()) + metaDataOk = true; + } else { QString iid = library->metaData.value(QLatin1String("IID")).toString(); if (iid == QLatin1String(d->iid.constData(), d->iid.size())) { QJsonObject object = library->metaData.value(QLatin1String("MetaData")).toObject(); + if (!object.isEmpty()) + metaDataOk = true; + QJsonArray k = object.value(QLatin1String("Keys")).toArray(); for (int i = 0; i < k.size(); ++i) { QString s = k.at(i).toString(); @@ -178,11 +188,12 @@ void QFactoryLoader::update() qDebug() << "Got keys from plugin meta data" << keys; } - if (keys.isEmpty()) { + if (!metaDataOk) { library->unload(); library->release(); continue; } + d->libraryList += library; for (int k = 0; k < keys.count(); ++k) { // first come first serve, unless the first -- cgit v1.2.3 From ff25691d00d634068c6389f8f1607d7cc95ac5be Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Thu, 1 Mar 2012 10:36:38 +0100 Subject: QNam: only init channels when needed. Each channel will create a socket that will allocate memory for the read and write buffers. QNam generaly inits 6 sockets for each connection. That means that by default 12 such buffers are created. This will instead initialize channels when they are needed. Change-Id: Ie3f2cf789e084fd3d17d3b2a9bb3d3a4370b3da4 Reviewed-by: Shane Kearns --- src/network/access/qhttpnetworkconnection.cpp | 106 ++++++++++++--------- .../access/qhttpnetworkconnectionchannel.cpp | 67 ++++++++++++- .../access/qhttpnetworkconnectionchannel_p.h | 11 +++ 3 files changed, 138 insertions(+), 46 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 6aa3a5a5f4..890072eb7e 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -123,8 +123,8 @@ void QHttpNetworkConnectionPrivate::init() //push session down to channels channels[i].networkSession = networkSession; #endif - channels[i].init(); } + delayedConnectionTimer.setSingleShot(true); QObject::connect(&delayedConnectionTimer, SIGNAL(timeout()), q, SLOT(_q_connectDelayedChannel())); } @@ -135,12 +135,14 @@ void QHttpNetworkConnectionPrivate::pauseConnection() // Disable all socket notifiers for (int i = 0; i < channelCount; i++) { + if (channels[i].socket) { #ifndef QT_NO_SSL - if (encrypt) - QSslSocketPrivate::pauseSocketNotifiers(static_cast(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::pauseSocketNotifiers(static_cast(channels[i].socket)); + else #endif - QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket); + QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket); + } } } @@ -149,16 +151,18 @@ void QHttpNetworkConnectionPrivate::resumeConnection() state = RunningState; // Enable all socket notifiers for (int i = 0; i < channelCount; i++) { + if (channels[i].socket) { #ifndef QT_NO_SSL - if (encrypt) - QSslSocketPrivate::resumeSocketNotifiers(static_cast(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::resumeSocketNotifiers(static_cast(channels[i].socket)); + else #endif - QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket); + QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket); - // Resume pending upload if needed - if (channels[i].state == QHttpNetworkConnectionChannel::WritingState) - QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection); + // Resume pending upload if needed + if (channels[i].state == QHttpNetworkConnectionChannel::WritingState) + QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection); + } } // queue _q_startNextRequest @@ -346,11 +350,15 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, QNetworkReply::NetworkError errorCode) { Q_Q(QHttpNetworkConnection); - if (socket && reply) { + + int i = 0; + if (socket) + i = indexOf(socket); + + if (reply) { // this error matters only to this reply reply->d_func()->errorString = errorDetail(errorCode, socket); emit reply->finishedWithError(errorCode, reply->d_func()->errorString); - int i = indexOf(socket); // remove the corrupt data if any reply->d_func()->eraseData(); @@ -358,7 +366,8 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, channels[i].close(); channels[i].reply = 0; channels[i].request = QHttpNetworkRequest(); - channels[i].requeueCurrentlyPipelinedRequests(); + if (socket) + channels[i].requeueCurrentlyPipelinedRequests(); // send the next request QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); @@ -582,9 +591,9 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket) { - Q_ASSERT(socket); - - int i = indexOf(socket); + int i = 0; + if (socket) + i = indexOf(socket); if (!highPriorityQueue.isEmpty()) { // remove from queue before sendRequest! else we might pipeline the same request again @@ -740,15 +749,15 @@ bool QHttpNetworkConnectionPrivate::fillPipeline(QList &queue, } -QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket, - const QString &extraDetail) +QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket, const QString &extraDetail) { - Q_ASSERT(socket); - QString errorString; switch (errorCode) { case QNetworkReply::HostNotFoundError: - errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName()); + if (socket) + errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName()); + else + errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(hostName); break; case QNetworkReply::ConnectionRefusedError: errorString = QCoreApplication::translate("QHttp", "Connection refused"); @@ -891,9 +900,11 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() return; // try to get a free AND connected socket for (int i = 0; i < channelCount; ++i) { - if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { - if (dequeueRequest(channels[i].socket)) - channels[i].sendRequest(); + if (channels[i].socket) { + if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { + if (dequeueRequest(channels[i].socket)) + channels[i].sendRequest(); + } } } @@ -908,7 +919,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) return; for (int i = 0; i < channelCount; i++) - if (channels[i].socket->state() == QAbstractSocket::ConnectedState) + if (channels[i].socket && channels[i].socket->state() == QAbstractSocket::ConnectedState) fillPipeline(channels[i].socket); // If there is not already any connected channels we need to connect a new one. @@ -916,11 +927,19 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() // connected or not. This is to reuse connected channels before we connect new once. int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count(); for (int i = 0; i < channelCount; ++i) { - if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState)) - queuedRequest--; - if ( queuedRequest <=0 ) - break; - if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) { + bool connectChannel = false; + if (channels[i].socket) { + if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState)) + queuedRequest--; + if ( queuedRequest <=0 ) + break; + if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) + connectChannel = true; + } else { // not previously used channel + connectChannel = true; + } + + if (connectChannel) { if (networkLayerState == IPv4) channels[i].networkLayerPreference = QAbstractSocket::IPv4Protocol; else if (networkLayerState == IPv6) @@ -928,6 +947,9 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() channels[i].ensureConnection(); queuedRequest--; } + + if ( queuedRequest <=0 ) + break; } } @@ -958,8 +980,8 @@ void QHttpNetworkConnectionPrivate::startHostInfoLookup() #ifndef QT_NO_NETWORKPROXY if (networkProxy.capabilities() & QNetworkProxy::HostNameLookupCapability) { lookupHost = networkProxy.hostName(); - } else if (channels[0].socket->proxy().capabilities() & QNetworkProxy::HostNameLookupCapability) { - lookupHost = channels[0].socket->proxy().hostName(); + } else if (channels[0].proxy.capabilities() & QNetworkProxy::HostNameLookupCapability) { + lookupHost = channels[0].proxy.hostName(); } #endif QHostAddress temp; @@ -1169,7 +1191,7 @@ void QHttpNetworkConnection::setTransparentProxy(const QNetworkProxy &networkPro { Q_D(QHttpNetworkConnection); for (int i = 0; i < d->channelCount; ++i) - d->channels[i].socket->setProxy(networkProxy); + d->channels[i].setProxy(networkProxy); } QNetworkProxy QHttpNetworkConnection::transparentProxy() const @@ -1190,7 +1212,7 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config // set the config on all channels for (int i = 0; i < d->channelCount; ++i) - static_cast(d->channels[i].socket)->setSslConfiguration(config); + d->channels[i].setSslConfiguration(config); } void QHttpNetworkConnection::ignoreSslErrors(int channel) @@ -1201,13 +1223,11 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel) if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { - static_cast(d->channels[i].socket)->ignoreSslErrors(); - d->channels[i].ignoreAllSslErrors = true; + d->channels[i].ignoreSslErrors(); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(); - d->channels[channel].ignoreAllSslErrors = true; + d->channels[channel].ignoreSslErrors(); } } @@ -1219,13 +1239,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList &errors, int if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { - static_cast(d->channels[i].socket)->ignoreSslErrors(errors); - d->channels[i].ignoreSslErrorsList = errors; + d->channels[i].ignoreSslErrors(errors); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(errors); - d->channels[channel].ignoreSslErrorsList = errors; + d->channels[channel].ignoreSslErrors(errors); } } diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 3991bffa47..a009222bd5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) , ssl(false) + , isInitialized(false) , state(IdleState) , reply(0) , written(0) @@ -152,19 +153,38 @@ void QHttpNetworkConnectionChannel::init() QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), this, SLOT(_q_encryptedBytesWritten(qint64)), Qt::DirectConnection); + + if (ignoreAllSslErrors) + sslSocket->ignoreSslErrors(); + + if (!ignoreSslErrorsList.isEmpty()) + sslSocket->ignoreSslErrors(ignoreSslErrorsList); + + if (!sslConfiguration.isNull()) + sslSocket->setSslConfiguration(sslConfiguration); } + #endif + +#ifndef QT_NO_NETWORKPROXY + if (proxy.type() != QNetworkProxy::NoProxy) + socket->setProxy(proxy); +#endif + isInitialized = true; } void QHttpNetworkConnectionChannel::close() { - if (socket->state() == QAbstractSocket::UnconnectedState) + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) state = QHttpNetworkConnectionChannel::IdleState; else state = QHttpNetworkConnectionChannel::ClosingState; - socket->close(); + if (socket) + socket->close(); } @@ -527,6 +547,9 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF() bool QHttpNetworkConnectionChannel::ensureConnection() { + if (!isInitialized) + init(); + QAbstractSocket::SocketState socketState = socket->state(); // resend this request after we receive the disconnected signal @@ -835,6 +858,46 @@ bool QHttpNetworkConnectionChannel::resetUploadData() } } +#ifndef QT_NO_NETWORKPROXY + +void QHttpNetworkConnectionChannel::setProxy(const QNetworkProxy &networkProxy) +{ + if (socket) + socket->setProxy(networkProxy); + + proxy = networkProxy; +} + +#endif + +#ifndef QT_NO_SSL + +void QHttpNetworkConnectionChannel::ignoreSslErrors() +{ + if (socket) + static_cast(socket)->ignoreSslErrors(); + + ignoreAllSslErrors = true; +} + + +void QHttpNetworkConnectionChannel::ignoreSslErrors(const QList &errors) +{ + if (socket) + static_cast(socket)->ignoreSslErrors(errors); + + ignoreSslErrorsList = errors; +} + +void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration &config) +{ + if (socket) + static_cast(socket)->setSslConfiguration(config); + + sslConfiguration = config; +} + +#endif void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 7da9b514d6..2648cba2a5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -72,6 +72,7 @@ #ifndef QT_NO_SSL # include # include +# include #else # include #endif @@ -100,6 +101,7 @@ public: }; QAbstractSocket *socket; bool ssl; + bool isInitialized; ChannelState state; QHttpNetworkRequest request; // current request QHttpNetworkReply *reply; // current reply for this request @@ -118,6 +120,10 @@ public: #ifndef QT_NO_SSL bool ignoreAllSslErrors; QList ignoreSslErrorsList; + QSslConfiguration sslConfiguration; + void ignoreSslErrors(); + void ignoreSslErrors(const QList &errors); + void setSslConfiguration(const QSslConfiguration &config); #endif #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession; @@ -144,6 +150,11 @@ public: void setConnection(QHttpNetworkConnection *c); QPointer connection; +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy proxy; + void setProxy(const QNetworkProxy &networkProxy); +#endif + void init(); void close(); -- cgit v1.2.3 From 703ef4f79edb30b8cf90c5bb62b1adf7acba55ff Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 3 Feb 2012 18:34:56 +0100 Subject: make QMakeProject's copy c'tor actually behave like one instead of initializing base_vars with the original's vars, initialize vars itself. this has two consequences: - there is no need to call read(0) to initialize vars - one cannot usefully call the complex read() anymore, as that would re-initialize vars from base_vars this is much closer to an actual copy than the previous "seeding with existing project". Change-Id: Ib007bc5b779aedb680a27329aa578f7c604a4308 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/generators/mac/pbuilder_pbx.cpp | 1 - qmake/project.cpp | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 70efff0bcd..770a1ad34e 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -178,7 +178,6 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t) } if(tmp_proj.first("TEMPLATE") == "subdirs") { QMakeProject *pp = new QMakeProject(&tmp_proj); - pp->read(0); pb_subdirs += new ProjectBuilderSubDirs(pp, dir); } else if(tmp_proj.first("TEMPLATE") == "app" || tmp_proj.first("TEMPLATE") == "lib") { QString pbxproj = qmake_getpwd() + Option::dir_sep + tmp_proj.first("TARGET") + projectSuffix(); diff --git a/qmake/project.cpp b/qmake/project.cpp index ecd31d5234..7f73b1f56f 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -627,10 +627,11 @@ QMakeProject::init(QMakeProperty *p) reset(); } -QMakeProject::QMakeProject(QMakeProject *p, const QHash *vars) +// Duplicate project. It is *not* allowed to call the complex read() functions on the copy. +QMakeProject::QMakeProject(QMakeProject *p, const QHash *_vars) { init(p->properties()); - base_vars = vars ? *vars : p->variables(); + vars = _vars ? *_vars : p->variables(); for(QHash::iterator it = p->replaceFunctions.begin(); it != p->replaceFunctions.end(); ++it) { it.value()->ref(); replaceFunctions.insert(it.key(), it.value()); -- cgit v1.2.3 From 84ddc063805deaa6e76eeff56076f5f359635073 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 30 Jan 2012 15:47:45 +0100 Subject: do not re-evaluate spec+cache in build passes clean up the somewhat convoluted code paths which forced re-evaluation. now that the spec+cache are evaluated in a completely clean context anyway, there is no point in re-evaluating them for build passes. Change-Id: I12279083238e9ca7028af97f45e2638c8dc715b8 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- qmake/project.cpp | 7 +++---- qmake/project.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/qmake/project.cpp b/qmake/project.cpp index 7f73b1f56f..35aaee9775 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1257,7 +1257,7 @@ QMakeProject::read(const QString &project, uchar cmd) bool QMakeProject::read(uchar cmd) { - if(cfile.isEmpty()) { + if ((cmd & ReadSetup) && base_vars.isEmpty()) { // hack to get the Option stuff in there base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; base_vars["QMAKE_EXT_C"] = Option::c_ext; @@ -1266,12 +1266,12 @@ QMakeProject::read(uchar cmd) if(!Option::user_template_prefix.isEmpty()) base_vars["TEMPLATE_PREFIX"] = QStringList(Option::user_template_prefix); - if ((cmd & ReadSetup) && Option::mkfile::do_cache) { // parse the cache + if (Option::mkfile::do_cache) { // parse the cache if (Option::output_dir.startsWith(Option::mkfile::project_build_root)) Option::mkfile::cachefile_depth = Option::output_dir.mid(Option::mkfile::project_build_root.length()).count('/'); } - if (cmd & ReadSetup) { // parse mkspec + { // parse mkspec QString qmakespec = Option::mkfile::qmakespec; while(qmakespec.endsWith(QLatin1Char('/'))) qmakespec.truncate(qmakespec.length()-1); @@ -1307,7 +1307,6 @@ QMakeProject::read(uchar cmd) //before commandline if (cmd & ReadSetup) { - cfile = pfile; parser.file = "(internal)"; parser.from_file = false; parser.line_no = 1; //really arg count now.. duh diff --git a/qmake/project.h b/qmake/project.h index 6422ed1f32..979f1480bd 100644 --- a/qmake/project.h +++ b/qmake/project.h @@ -81,7 +81,7 @@ class QMakeProject bool recursive; bool own_prop; bool backslashWarned; - QString pfile, cfile; + QString pfile; QMakeProperty *prop; void reset(); QStringList extra_configs; -- cgit v1.2.3 From 95fa88abe7441f49b64a0b398e16b04b3b6bdbc9 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 1 Feb 2012 00:33:30 +0200 Subject: Remove codecForTr(). Similarly to change id I2f429fa7ef93bd75bb93a7f64c56db15b7283388, the capability to arbitrarily alter the encoding of literals is very destructive, especially in a world with libraries and plugins. Change-Id: If0d4cd8dcf89792e39c1984cbde6b036cebfc02f Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- dist/changes-5.0.0 | 4 ++++ src/corelib/codecs/qtextcodec.cpp | 37 --------------------------------- src/corelib/codecs/qtextcodec.h | 7 ------- src/corelib/global/qglobal.cpp | 4 +--- src/corelib/kernel/qcoreapplication.cpp | 14 +++++-------- src/corelib/kernel/qcoreapplication.h | 6 +++--- src/corelib/kernel/qmetaobject.cpp | 2 +- src/corelib/kernel/qobject.cpp | 7 +------ 8 files changed, 15 insertions(+), 66 deletions(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 9644df40a4..93f8543fd8 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -310,6 +310,10 @@ QtCore libraries, creating uncertainty/bugs in using QString easily, and (to a lesser extent) performance issues. +* QTextCodec::codecForTr() and QTextCodec::setCodecForTr() have been removed, + QCoreApplication::Encoding value CodecForTr is now obsolete, use + DefaultCodec instead. For reasoning, see the codecForCStrings() removal above. + * QIntValidator and QDoubleValidator no longer fall back to using the C locale if the requested locale fails to validate the input. diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index f6f0cd8699..13f0ec8ce5 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -145,8 +145,6 @@ static bool destroying_is_ok = false; #endif static QTextCodec *localeMapper = 0; -QTextCodec *QTextCodec::cftr = 0; - class QTextCodecCleanup { @@ -1463,41 +1461,6 @@ QString QTextDecoder::toUnicode(const QByteArray &ba) return c->toUnicode(ba.constData(), ba.length(), &state); } - -/*! - \fn QTextCodec* QTextCodec::codecForTr() - - Returns the codec used by QObject::tr() on its argument. If this - function returns 0 (the default), tr() assumes Latin-1. - - \sa setCodecForTr() -*/ - -/*! - \fn void QTextCodec::setCodecForTr(QTextCodec *c) - \nonreentrant - - Sets the codec used by QObject::tr() on its argument to \a c. If - \a c is 0 (the default), tr() assumes Latin-1. - - If the literal quoted text in the program is not in the Latin-1 - encoding, this function can be used to set the appropriate - encoding. For example, software developed by Korean programmers - might use eucKR for all the text in the program, in which case the - main() function might look like this: - - \snippet doc/src/snippets/code/src_corelib_codecs_qtextcodec.cpp 3 - - Note that this is not the way to select the encoding that the \e - user has chosen. For example, to convert an application containing - literal English strings to Korean, all that is needed is for the - English strings to be passed through tr() and for translation - files to be loaded. For details of internationalization, see - \l{Internationalization with Qt}. - - \sa codecForTr() -*/ - /*! \since 4.4 diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h index ad37005e92..b4b170f7d7 100644 --- a/src/corelib/codecs/qtextcodec.h +++ b/src/corelib/codecs/qtextcodec.h @@ -72,9 +72,6 @@ public: static QTextCodec* codecForLocale(); static void setCodecForLocale(QTextCodec *c); - static QTextCodec* codecForTr(); - static void setCodecForTr(QTextCodec *c); - static QTextCodec *codecForHtml(const QByteArray &ba); static QTextCodec *codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec); @@ -129,14 +126,10 @@ protected: private: friend class QTextCodecCleanup; - static QTextCodec *cftr; static bool validCodecs(); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextCodec::ConversionFlags) - inline QTextCodec* QTextCodec::codecForTr() { return validCodecs() ? cftr : 0; } -inline void QTextCodec::setCodecForTr(QTextCodec *c) { cftr = c; } - class Q_CORE_EXPORT QTextEncoder { Q_DISABLE_COPY(QTextEncoder) public: diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index a30250df81..09d178639d 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2233,9 +2233,7 @@ int qrand() The macro QT_TR_NOOP_UTF8() is identical except that it tells lupdate that the source string is encoded in UTF-8. Corresponding variants - exist in the QT_TRANSLATE_NOOP() family of macros, too. Note that - using these macros is not required if \c CODECFORTR is already set to - UTF-8 in the qmake project file. + exist in the QT_TRANSLATE_NOOP() family of macros, too. \sa QT_TRANSLATE_NOOP(), {Internationalization with Qt} */ diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 515732bc68..184743e865 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1438,11 +1438,9 @@ bool QCoreApplication::event(QEvent *e) This enum type defines the 8-bit encoding of character string arguments to translate(): - \value CodecForTr The encoding specified by - QTextCodec::codecForTr() (Latin-1 if none has - been set). - \value UnicodeUTF8 UTF-8. - \value DefaultCodec (Obsolete) Use CodecForTr instead. + \value UnicodeUTF8 UTF-8. + \value Latin1 Latin-1. + \value DefaultCodec Latin-1. \sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8() */ @@ -1617,7 +1615,7 @@ static void replacePercentN(QString *result, int n) If none of the translation files contain a translation for \a sourceText in \a context, this function returns a QString equivalent of \a sourceText. The encoding of \a sourceText is - specified by \e encoding; it defaults to CodecForTr. + specified by \e encoding; it defaults to DefaultCodec. This function is not virtual. You can use alternative translation techniques by subclassing \l QTranslator. @@ -1628,7 +1626,7 @@ static void replacePercentN(QString *result, int n) so will most likely result in crashes or other undesirable behavior. - \sa QObject::tr() installTranslator() QTextCodec::codecForTr() + \sa QObject::tr() installTranslator() */ @@ -1657,8 +1655,6 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, #else if (encoding == UnicodeUTF8) result = QString::fromUtf8(sourceText); - else if (QTextCodec::codecForTr() != 0) - result = QTextCodec::codecForTr()->toUnicode(sourceText); else #endif result = QString::fromLatin1(sourceText); diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 18266a9a2c..0a5181a508 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -137,11 +137,11 @@ public: static void installTranslator(QTranslator * messageFile); static void removeTranslator(QTranslator * messageFile); #endif - enum Encoding { CodecForTr, UnicodeUTF8, DefaultCodec = CodecForTr }; + enum Encoding { UnicodeUTF8, Latin1, DefaultCodec = Latin1 }; static QString translate(const char * context, const char * key, const char * disambiguation = 0, - Encoding encoding = CodecForTr, + Encoding encoding = DefaultCodec, int n = -1); static void flush(); @@ -240,7 +240,7 @@ inline QString QCoreApplication::translate(const char *, const char *sourceText, public: \ static inline QString tr(const char *sourceText, const char *disambiguation = 0, int n = -1) \ { return QCoreApplication::translate(#context, sourceText, disambiguation, \ - QCoreApplication::CodecForTr, n); } \ + QCoreApplication::DefaultCodec, n); } \ static inline QString trUtf8(const char *sourceText, const char *disambiguation = 0, int n = -1) \ { return QCoreApplication::translate(#context, sourceText, disambiguation, \ QCoreApplication::UnicodeUTF8, n); } \ diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index f962fb7831..cacd999869 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -307,7 +307,7 @@ const QObject *QMetaObject::cast(const QObject *obj) const */ QString QMetaObject::tr(const char *s, const char *c, int n) const { - return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n); + return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::DefaultCodec, n); } /*! diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 19440e9368..3a4d1da592 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1859,7 +1859,7 @@ void QObject::deleteLater() translators while performing translations is not supported. Doing so will probably result in crashes or other undesirable behavior. - \sa trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt} + \sa trUtf8(), QApplication::translate(), {Internationalization with Qt} */ /*! @@ -1871,11 +1871,6 @@ void QObject::deleteLater() version. It is otherwise identical to tr(\a sourceText, \a disambiguation, \a n). - Note that using the Utf8 variants of the translation functions - is not required if \c CODECFORTR is already set to UTF-8 in the - qmake project file and QTextCodec::setCodecForTr("UTF-8") is - used. - \warning This method is reentrant only if all translators are installed \e before calling this method. Installing or removing translators while performing translations is not supported. Doing -- cgit v1.2.3 From cf785e0419f48dc24c35308d6dc61f1103980b3b Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Mon, 5 Mar 2012 17:48:22 +0900 Subject: Add missing Q_OBJECT macro to QCoreTextFontEngine Change-Id: I5d6b4742265a026d404d5ffa48f2c554d5483f30 Reviewed-by: Jiang Jiang --- src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index bfa2841158..d32f05022e 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE class QRawFontPrivate; class QCoreTextFontEngine : public QFontEngine { + Q_OBJECT public: QCoreTextFontEngine(CTFontRef font, const QFontDef &def); QCoreTextFontEngine(CGFontRef font, const QFontDef &def); -- cgit v1.2.3 From e3027377f0e7598c00b56962f08cb15b568f2356 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Fri, 2 Mar 2012 08:53:03 +0900 Subject: QWindow: fix crash on Mac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a crash when QWindow::baseSize() is invalid size. Change-Id: I4e41f63d69ad0f218bfd35db8f30f18f92d4e9d5 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b2e93470c9..3f566ccb44 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -201,7 +201,7 @@ void QCocoaWindow::propagateSizeHints() [m_nsWindow setResizeIncrements : qt_mac_toNSSize(window()->sizeIncrement())]; QSize baseSize = window()->baseSize(); - if (!baseSize.isNull()) { + if (!baseSize.isNull() && baseSize.isValid()) { [m_nsWindow setFrameSize : NSMakeSize(baseSize.width(), baseSize.height()) display : YES]; } } -- cgit v1.2.3 From 4a80a7ced1f643a6794f6550d01c1fe60295a21c Mon Sep 17 00:00:00 2001 From: Rick Stockton Date: Mon, 6 Feb 2012 17:20:08 -0800 Subject: add widget mousebuttons example 'mousetester'. This is an xev-like program. A user clicks a mouse button inside the Window, and the program displays (a) the "raw" button number; (b) the corresponding Qt::MouseButton name; and (c) the type of mouse Event. Task-number: QTBUG-24112 Change-Id: I8a76ff37b5b85639f662706072cc4a2ce490754b Reviewed-by: Casper van Donderen --- doc/src/examples/widgets/mousebuttons.qdoc | 94 +++++++++++ .../images/widgets/mousebutton-buttontester.png | Bin 0 -> 14492 bytes examples/widgets/mousebuttons/buttontester.cpp | 172 +++++++++++++++++++++ examples/widgets/mousebuttons/buttontester.h | 64 ++++++++ examples/widgets/mousebuttons/buttontester.pro | 18 +++ examples/widgets/mousebuttons/main.cpp | 66 ++++++++ examples/widgets/widgets.pro | 1 + 7 files changed, 415 insertions(+) create mode 100644 doc/src/examples/widgets/mousebuttons.qdoc create mode 100644 doc/src/images/widgets/mousebutton-buttontester.png create mode 100644 examples/widgets/mousebuttons/buttontester.cpp create mode 100644 examples/widgets/mousebuttons/buttontester.h create mode 100644 examples/widgets/mousebuttons/buttontester.pro create mode 100644 examples/widgets/mousebuttons/main.cpp diff --git a/doc/src/examples/widgets/mousebuttons.qdoc b/doc/src/examples/widgets/mousebuttons.qdoc new file mode 100644 index 0000000000..bf63cd5076 --- /dev/null +++ b/doc/src/examples/widgets/mousebuttons.qdoc @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2012 Rick Stockton +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example widgets/mousebuttons/buttontester + \title Mouse Button Tester + + \brief The 'Mouse Button Tester' example demonstrates how to reimplement + mouse events within a custom class. You can also use this program to + verify that Qt is actually receiving mouse events from your mouse. + + Many 'gamer' mouse devices are configured with high-numbered "buttons" + sending text shortcuts for certain games. With such a mouse, no mouse + button events occur: The "mouse" sends keystrokes, and the + 'Mouse Button Tester' Window will not see the event. Receving no event, + it will not repaint the Window with new text describing a \button event. + + And so, in addition to it's use as Qt example code, the program may be + useful s a mouse device tester. Note that there is another example + muouse buttons example which provides the same function, written in QML. + + This program (the Widget-based example) consists of three classes, + in addition to the main() parent program: + + \list + \o \c A QPushButton, "Quit". + \o \c ButtonTester. This is derived from Qt's TextArea class, for + purpose of customizing/re-implementing the mouse and wheel event + member functions. + \o \c A simple QVBoxLayout layout. + \endlist + + First we will review the main program, with it's layout and "Quit" + QPushButton. Then we will take a look at the \c ButtonTester class. + + \section1 The Main Program + + Note that the QPushButton, "Quit", is defined directly within the main() + program, rather than another class. This is a correct way of defining a + "Quit" QPushButton: A "Quit" Button defined inside another + class would result in the destructor of that second class being + called twice. This "Quit" Button uses the traditional Signal/Slot + connection to invoke termination of the QApp, which will properly destroy + its child classes \before terminating itself. + + The remainder of the main() program is concerned with defining the layout, + and applying a minimum size to the customized ButtonTester. + + \section1 ButtonTester Class Definition + + The \c ButtonTester class inherits from QTextEdit, and listens for + mouse events on all possible Qt::MouseButton values. It also listens for + wheel events from the mouse, and indicates the direction of wheel motion + ("up", down", "left", or "right"). It prints short debug messages into + the Window, and also on the console QDebug() stream, when mouse button + and wheel events occur. Our reimplementation of mousePressEvent(), + mouseReleaseEvent(), mouseDoubleClickEvent(), and wheelEvent() "drive" + the program; the other functions simply convert the Qt::MouseButton + values into text strings. + + You should call the ignore() function on any mouse event (or other event) + which your widget-based classes do not use and consume. This function + assures that Qt will propagate the event through each parent widget, + until it is used or propagated to the Window Manager. (Qt attempts to do + this automatically, but it is better programming practice to explicitly + invoke the function.) + + \image widgets/mousebutton-buttontester.png +*/ diff --git a/doc/src/images/widgets/mousebutton-buttontester.png b/doc/src/images/widgets/mousebutton-buttontester.png new file mode 100644 index 0000000000..82fcb7617f Binary files /dev/null and b/doc/src/images/widgets/mousebutton-buttontester.png differ diff --git a/examples/widgets/mousebuttons/buttontester.cpp b/examples/widgets/mousebuttons/buttontester.cpp new file mode 100644 index 0000000000..32f73ebb72 --- /dev/null +++ b/examples/widgets/mousebuttons/buttontester.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2012 Rick Stockton +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "buttontester.h" + +void ButtonTester::mousePressEvent(QMouseEvent *e) +{ + int j = ButtonTester::buttonByNumber (e->button()); + QString result = "Mouse Press: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button()); + qDebug() << result; + this->setText(result); + if (j == 2) { + this->repaint(); + } +} + +void ButtonTester::mouseReleaseEvent(QMouseEvent *e) +{ + int j = ButtonTester::buttonByNumber (e->button()); + QString result = "Mouse Release: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button()); + qDebug() << result; + this->setText(result); +} + +void ButtonTester::mouseDoubleClickEvent(QMouseEvent *e) +{ + int j = ButtonTester::buttonByNumber (e->button()); + QString result = "Mouse DoubleClick: raw button=" + QString::number(j) + " Qt=" + enumNameFromValue(e->button()); + qDebug() << result; + this->setText(result); +} + +void ButtonTester::wheelEvent (QWheelEvent *e) +{ + QString result; + if (e->delta() > 0) { + + if (e->orientation() == Qt::Vertical) { + result = "Mouse Wheel Event: UP"; + } else { + result = "Mouse Wheel Event: LEFT"; + } + } else if (e->delta() < 0) { + if (e->orientation() == Qt::Vertical) { + result = "Mouse Wheel Event: DOWN"; + } else { + result = "Mouse Wheel Event: RIGHT"; + } + } + qDebug() << result; + this->setText(result); +} + +int ButtonTester::buttonByNumber(const Qt::MouseButton button) +{ + if (button == Qt::NoButton) return 0; + if (button == Qt::LeftButton) return 1; + if (button == Qt::RightButton) return 2; + if (button == Qt::MiddleButton) return 3; + +/* Please note that Qt Button #4 corresponds to button #8 on all + * platforms which EMULATE wheel events by creating button events + * (Button #4 = Scroll Up; Button #5 = Scroll Down; Button #6 = Scroll + * Left; and Button #7 = Scroll Right.) This includes X11, with both + * Xlib and XCB. So, the "raw button" for "Qt::BackButton" is + * usually described as "Button #8". + + * If your platform supports "smooth scrolling", then, for the cases of + * Qt::BackButton and higher, this program will show "raw button" with a + * value which is too large. Subtract 4 to get the correct button ID for + * your platform. + */ + + if (button == Qt::BackButton) return 8; + if (button == Qt::ForwardButton) return 9; + if (button == Qt::TaskButton) return 10; + if (button == Qt::ExtraButton4) return 11; + if (button == Qt::ExtraButton5) return 12; + if (button == Qt::ExtraButton6) return 13; + if (button == Qt::ExtraButton7) return 14; + if (button == Qt::ExtraButton8) return 15; + if (button == Qt::ExtraButton9) return 16; + if (button == Qt::ExtraButton10) return 17; + if (button == Qt::ExtraButton11) return 18; + if (button == Qt::ExtraButton12) return 19; + if (button == Qt::ExtraButton13) return 20; + if (button == Qt::ExtraButton14) return 21; + if (button == Qt::ExtraButton15) return 22; + if (button == Qt::ExtraButton16) return 23; + if (button == Qt::ExtraButton17) return 24; + if (button == Qt::ExtraButton18) return 25; + if (button == Qt::ExtraButton19) return 26; + if (button == Qt::ExtraButton20) return 27; + if (button == Qt::ExtraButton21) return 28; + if (button == Qt::ExtraButton22) return 29; + if (button == Qt::ExtraButton23) return 30; + if (button == Qt::ExtraButton24) return 31; + qDebug("QMouseShortcutEntry::addShortcut contained Invalid Qt::MouseButton value"); + return 0; +} + +QString ButtonTester::enumNameFromValue(const Qt::MouseButton button) +{ + if (button == Qt::NoButton) return "NoButton"; + if (button == Qt::LeftButton) return "LeftButton"; + if (button == Qt::RightButton) return "RightButton"; + if (button == Qt::MiddleButton) return "MiddleButton"; + if (button == Qt::BackButton) return "BackButton"; + if (button == Qt::ForwardButton) return "ForwardButton"; + if (button == Qt::TaskButton) return "TaskButton"; + if (button == Qt::ExtraButton4) return "ExtraButton4"; + if (button == Qt::ExtraButton5) return "ExtraButton5"; + if (button == Qt::ExtraButton6) return "ExtraButton6"; + if (button == Qt::ExtraButton7) return "ExtraButton7"; + if (button == Qt::ExtraButton8) return "ExtraButton8"; + if (button == Qt::ExtraButton9) return "ExtraButton9"; + if (button == Qt::ExtraButton10) return "ExtraButton10"; + if (button == Qt::ExtraButton11) return "ExtraButton11"; + if (button == Qt::ExtraButton12) return "ExtraButton12"; + if (button == Qt::ExtraButton13) return "ExtraButton13"; + if (button == Qt::ExtraButton14) return "ExtraButton14"; + if (button == Qt::ExtraButton15) return "ExtraButton15"; + if (button == Qt::ExtraButton16) return "ExtraButton16"; + if (button == Qt::ExtraButton17) return "ExtraButton17"; + if (button == Qt::ExtraButton18) return "ExtraButton18"; + if (button == Qt::ExtraButton19) return "ExtraButton19"; + if (button == Qt::ExtraButton20) return "ExtraButton20"; + if (button == Qt::ExtraButton21) return "ExtraButton21"; + if (button == Qt::ExtraButton22) return "ExtraButton22"; + if (button == Qt::ExtraButton23) return "ExtraButton23"; + if (button == Qt::ExtraButton24) return "ExtraButton24"; + qDebug("QMouseShortcutEntry::addShortcut contained Invalid Qt::MouseButton value"); + return "NoButton"; +} diff --git a/examples/widgets/mousebuttons/buttontester.h b/examples/widgets/mousebuttons/buttontester.h new file mode 100644 index 0000000000..0801a9ae5c --- /dev/null +++ b/examples/widgets/mousebuttons/buttontester.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2012 Rick Stockton +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef BUTTONTESTER_H +#define BUTTONTESTER_H + +#include +#include +#include +#include +#include +#include + +class ButtonTester : public QTextEdit +{ + Q_OBJECT + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event); + int buttonByNumber(const Qt::MouseButton button); + QString enumNameFromValue(const Qt::MouseButton button); +}; + +#endif // BUTTONTESTER_H diff --git a/examples/widgets/mousebuttons/buttontester.pro b/examples/widgets/mousebuttons/buttontester.pro new file mode 100644 index 0000000000..823b04657e --- /dev/null +++ b/examples/widgets/mousebuttons/buttontester.pro @@ -0,0 +1,18 @@ +TEMPLATE = app + +TARGET = buttontester +TEMPLATE = app + +SOURCES += \ + main.cpp\ + buttontester.cpp \ + +HEADERS += \ + buttontester.h \ + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS buttontester.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons +INSTALLS += target sources +QT += core widgets diff --git a/examples/widgets/mousebuttons/main.cpp b/examples/widgets/mousebuttons/main.cpp new file mode 100644 index 0000000000..7c9674a9d9 --- /dev/null +++ b/examples/widgets/mousebuttons/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2012 Rick Stockton +** Contact: http://www.qt-project.org/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "buttontester.h" +#include + +int main(int argv, char **args) +{ + QApplication app(argv, args); + + ButtonTester *testArea = new ButtonTester; + testArea->setMinimumSize(500, 350); + testArea->setText("To test your mouse with Qt, press buttons in this area.\nYou may also scroll or tilt your mouse wheel."); + QPushButton *quitButton = new QPushButton("Quit"); + + QObject::connect(quitButton, SIGNAL(clicked()), qApp, SLOT(quit())); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(testArea); + layout->addWidget(quitButton); + + QWidget window; + window.setLayout(layout); + window.setWindowTitle("Mouse Button Tester"); + window.show(); + + return app.exec(); +} diff --git a/examples/widgets/widgets.pro b/examples/widgets/widgets.pro index 51a92bcc29..f5c98c3c77 100644 --- a/examples/widgets/widgets.pro +++ b/examples/widgets/widgets.pro @@ -12,6 +12,7 @@ SUBDIRS = analogclock \ imageviewer \ lineedits \ movie \ + mousebuttons \ orientation \ scribble \ shapedclock \ -- cgit v1.2.3 From e6f84312a5352c742f240385e2814ef9b865db22 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 20 Feb 2012 10:30:07 +0100 Subject: qpa: Document a requirement of the backing store implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docuent the requirement that the alpha channels need to be properly initialized by the implementation. Change-Id: I03db81b44b43ea75feb1b983fb0725c65a3bd9f4 Reviewed-by: Samuel Rødal --- src/gui/painting/qplatformbackingstore_qpa.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/painting/qplatformbackingstore_qpa.cpp b/src/gui/painting/qplatformbackingstore_qpa.cpp index 485190d301..ff7d91ccea 100644 --- a/src/gui/painting/qplatformbackingstore_qpa.cpp +++ b/src/gui/painting/qplatformbackingstore_qpa.cpp @@ -114,6 +114,9 @@ QWindow* QPlatformBackingStore::window() const This function is called before painting onto the surface begins, with the \a region in which the painting will occur. + \note A platform providing a backing store with an alpha channel + needs to properly initialize the region to be painted. + \sa endPaint(), paintDevice() */ -- cgit v1.2.3 From dc75c20397e7322ba87578e766e0cd86ece90f93 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 26 Feb 2012 10:05:39 +0100 Subject: Split up base class QFileDevice for open-file operations (read/write) This will be used later on as a base class for QTemporaryFile and QSaveFile. Change-Id: Ic2e1d232f95dc29b8e2f75e24a881ab459d3f037 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll --- qmake/Makefile.unix | 6 +- qmake/Makefile.win32 | 1 + qmake/Makefile.win32-g++ | 1 + qmake/qmake.pri | 1 + src/corelib/io/io.pri | 3 + src/corelib/io/qfile.cpp | 635 +------------------------------- src/corelib/io/qfile.h | 62 +--- src/corelib/io/qfile_p.h | 20 +- src/corelib/io/qfiledevice.cpp | 736 ++++++++++++++++++++++++++++++++++++++ src/corelib/io/qfiledevice.h | 147 ++++++++ src/corelib/io/qfiledevice_p.h | 104 ++++++ src/tools/bootstrap/bootstrap.pro | 1 + tools/configure/Makefile.mingw | 1 + tools/configure/Makefile.win32 | 2 + tools/configure/configure.pro | 2 + 15 files changed, 1026 insertions(+), 696 deletions(-) create mode 100644 src/corelib/io/qfiledevice.cpp create mode 100644 src/corelib/io/qfiledevice.h create mode 100644 src/corelib/io/qfiledevice_p.h diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index d9835932d6..2dddecb7b0 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -15,7 +15,7 @@ OBJS=project.o property.o main.o makefile.o unixmake2.o unixmake.o \ #qt code QOBJS=qtextcodec.o qutfcodec.o qstring.o qtextstream.o qiodevice.o qmalloc.o qglobal.o \ - qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfile.o \ + qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \ qfilesystementry.o qfilesystemengine_unix.o qfilesystemengine.o qfilesystemiterator_unix.o \ qfsfileengine_unix.o qfsfileengine.o \ qfsfileengine_iterator.o qregexp.o qvector.o qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o \ @@ -37,6 +37,7 @@ DEPEND_SRC=project.cpp property.cpp meta.cpp main.cpp generators/makefile.cpp ge generators/integrity/gbuild.cpp \ $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \ $(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \ + $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \ $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \ $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \ $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \ @@ -176,6 +177,9 @@ qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp +qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp + qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index f640216036..f36e4fa631 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -82,6 +82,7 @@ QTOBJS= \ qdatetime.obj \ qdir.obj \ qdiriterator.obj \ + qfiledevice.obj \ qfile.obj \ qtemporaryfile.obj \ qabstractfileengine.obj \ diff --git a/qmake/Makefile.win32-g++ b/qmake/Makefile.win32-g++ index 57e6c1aa4e..56d8edca7d 100644 --- a/qmake/Makefile.win32-g++ +++ b/qmake/Makefile.win32-g++ @@ -84,6 +84,7 @@ QTOBJS= \ qdatetime.o \ qdir.o \ qdiriterator.o \ + qfiledevice.o \ qfile.o \ qtemporaryfile.o \ qfileinfo.o \ diff --git a/qmake/qmake.pri b/qmake/qmake.pri index abb073c48e..dda03d43b8 100644 --- a/qmake/qmake.pri +++ b/qmake/qmake.pri @@ -42,6 +42,7 @@ bootstrap { #Qt code qdatetime.cpp \ qdir.cpp \ qdiriterator.cpp \ + qfiledevice.cpp \ qfile.cpp \ qabstractfileengine.cpp \ qfileinfo.cpp \ diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 29599295ad..9c117abe03 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -11,6 +11,8 @@ HEADERS += \ io/qdir_p.h \ io/qdiriterator.h \ io/qfile.h \ + io/qfiledevice.h \ + io/qfiledevice_p.h \ io/qfileinfo.h \ io/qfileinfo_p.h \ io/qiodevice.h \ @@ -49,6 +51,7 @@ SOURCES += \ io/qdir.cpp \ io/qdiriterator.cpp \ io/qfile.cpp \ + io/qfiledevice.cpp \ io/qfileinfo.cpp \ io/qiodevice.cpp \ io/qnoncontiguousbytedevice.cpp \ diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 6640dca70b..433d4493e5 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE -static const int QFILE_WRITEBUFFER_SIZE = 16384; - static QByteArray locale_encode(const QString &f) { #if defined(Q_OS_DARWIN) @@ -86,16 +84,11 @@ QFile::EncoderFn QFilePrivate::encoder = locale_encode; QFile::DecoderFn QFilePrivate::decoder = locale_decode; QFilePrivate::QFilePrivate() - : fileEngine(0), lastWasWrite(false), - writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError), - cachedSize(0) { } QFilePrivate::~QFilePrivate() { - delete fileEngine; - fileEngine = 0; } bool @@ -137,39 +130,6 @@ QAbstractFileEngine *QFilePrivate::engine() const return fileEngine; } -inline bool QFilePrivate::ensureFlushed() const -{ - // This function ensures that the write buffer has been flushed (const - // because certain const functions need to call it. - if (lastWasWrite) { - const_cast(this)->lastWasWrite = false; - if (!const_cast(q_func())->flush()) - return false; - } - return true; -} - -void -QFilePrivate::setError(QFile::FileError err) -{ - error = err; - errorString.clear(); -} - -void -QFilePrivate::setError(QFile::FileError err, const QString &errStr) -{ - error = err; - errorString = errStr; -} - -void -QFilePrivate::setError(QFile::FileError err, int errNum) -{ - error = err; - errorString = qt_error_string(errNum); -} - //************* QFile /*! @@ -278,98 +238,18 @@ QFilePrivate::setError(QFile::FileError err, int errNum) \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System} */ -/*! - \enum QFile::FileError - - This enum describes the errors that may be returned by the error() - function. - - \value NoError No error occurred. - \value ReadError An error occurred when reading from the file. - \value WriteError An error occurred when writing to the file. - \value FatalError A fatal error occurred. - \value ResourceError - \value OpenError The file could not be opened. - \value AbortError The operation was aborted. - \value TimeOutError A timeout occurred. - \value UnspecifiedError An unspecified error occurred. - \value RemoveError The file could not be removed. - \value RenameError The file could not be renamed. - \value PositionError The position in the file could not be changed. - \value ResizeError The file could not be resized. - \value PermissionsError The file could not be accessed. - \value CopyError The file could not be copied. - - \omitvalue ConnectError -*/ - -/*! - \enum QFile::Permission - - This enum is used by the permission() function to report the - permissions and ownership of a file. The values may be OR-ed - together to test multiple permissions and ownership values. - - \value ReadOwner The file is readable by the owner of the file. - \value WriteOwner The file is writable by the owner of the file. - \value ExeOwner The file is executable by the owner of the file. - \value ReadUser The file is readable by the user. - \value WriteUser The file is writable by the user. - \value ExeUser The file is executable by the user. - \value ReadGroup The file is readable by the group. - \value WriteGroup The file is writable by the group. - \value ExeGroup The file is executable by the group. - \value ReadOther The file is readable by anyone. - \value WriteOther The file is writable by anyone. - \value ExeOther The file is executable by anyone. - - \warning Because of differences in the platforms supported by Qt, - the semantics of ReadUser, WriteUser and ExeUser are - platform-dependent: On Unix, the rights of the owner of the file - are returned and on Windows the rights of the current user are - returned. This behavior might change in a future Qt version. - - Note that Qt does not by default check for permissions on NTFS - file systems, as this may decrease the performance of file - handling considerably. It is possible to force permission checking - on NTFS by including the following code in your source: - - \snippet doc/src/snippets/ntfsp.cpp 0 - - Permission checking is then turned on and off by incrementing and - decrementing \c qt_ntfs_permission_lookup by 1. - - \snippet doc/src/snippets/ntfsp.cpp 1 -*/ - -/*! - \enum QFile::FileHandleFlag - - This enum is used when opening a file to specify additional - options which only apply to files and not to a generic - QIODevice. - - \value AutoCloseHandle The file handle passed into open() should be - closed by close(), the default behavior is that close just flushes - the file and the application is responsible for closing the file handle. - When opening a file by name, this flag is ignored as Qt always owns the - file handle and must close it. - \value DontCloseHandle If not explicitly closed, the underlying file - handle is left open when the QFile object is destroyed. - */ - #ifdef QT_NO_QOBJECT QFile::QFile() - : QIODevice(*new QFilePrivate) + : QFileDevice(*new QFilePrivate) { } QFile::QFile(const QString &name) - : QIODevice(*new QFilePrivate) + : QFileDevice(*new QFilePrivate) { d_func()->fileName = name; } QFile::QFile(QFilePrivate &dd) - : QIODevice(dd) + : QFileDevice(dd) { } #else @@ -377,21 +257,21 @@ QFile::QFile(QFilePrivate &dd) \internal */ QFile::QFile() - : QIODevice(*new QFilePrivate, 0) + : QFileDevice(*new QFilePrivate, 0) { } /*! Constructs a new file object with the given \a parent. */ QFile::QFile(QObject *parent) - : QIODevice(*new QFilePrivate, parent) + : QFileDevice(*new QFilePrivate, parent) { } /*! Constructs a new file object to represent the file with the given \a name. */ QFile::QFile(const QString &name) - : QIODevice(*new QFilePrivate, 0) + : QFileDevice(*new QFilePrivate, 0) { Q_D(QFile); d->fileName = name; @@ -401,7 +281,7 @@ QFile::QFile(const QString &name) file with the specified \a name. */ QFile::QFile(const QString &name, QObject *parent) - : QIODevice(*new QFilePrivate, parent) + : QFileDevice(*new QFilePrivate, parent) { Q_D(QFile); d->fileName = name; @@ -410,7 +290,7 @@ QFile::QFile(const QString &name, QObject *parent) \internal */ QFile::QFile(QFilePrivate &dd, QObject *parent) - : QIODevice(dd, parent) + : QFileDevice(dd, parent) { } #endif @@ -420,7 +300,6 @@ QFile::QFile(QFilePrivate &dd, QObject *parent) */ QFile::~QFile() { - close(); } /*! @@ -961,20 +840,6 @@ QFile::copy(const QString &fileName, const QString &newName) return QFile(fileName).copy(newName); } -/*! - Returns true if the file can only be manipulated sequentially; - otherwise returns false. - - Most files support random-access, but some special files may not. - - \sa QIODevice::isSequential() -*/ -bool QFile::isSequential() const -{ - Q_D(const QFile); - return d->fileEngine && d->fileEngine->isSequential(); -} - /*! Opens the file using OpenMode \a mode, returning true if successful; otherwise false. @@ -1149,119 +1014,11 @@ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags) } /*! - Returns the file handle of the file. - - This is a small positive integer, suitable for use with C library - functions such as fdopen() and fcntl(). On systems that use file - descriptors for sockets (i.e. Unix systems, but not Windows) the handle - can be used with QSocketNotifier as well. - - If the file is not open, or there is an error, handle() returns -1. - - This function is not supported on Windows CE. - - \sa QSocketNotifier -*/ - -int -QFile::handle() const -{ - Q_D(const QFile); - if (!isOpen() || !d->fileEngine) - return -1; - - return d->fileEngine->handle(); -} - -/*! - \enum QFile::MemoryMapFlags - \since 4.4 - - This enum describes special options that may be used by the map() - function. - - \value NoOptions No options. -*/ - -/*! - \since 4.4 - Maps \a size bytes of the file into memory starting at \a offset. A file - should be open for a map to succeed but the file does not need to stay - open after the memory has been mapped. When the QFile is destroyed - or a new file is opened with this object, any maps that have not been - unmapped will automatically be unmapped. - - Any mapping options can be passed through \a flags. - - Returns a pointer to the memory or 0 if there is an error. - - \note On Windows CE 5.0 the file will be closed before mapping occurs. - - \sa unmap() - */ -uchar *QFile::map(qint64 offset, qint64 size, MemoryMapFlags flags) -{ - Q_D(QFile); - if (d->engine() - && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) { - unsetError(); - uchar *address = d->fileEngine->map(offset, size, flags); - if (address == 0) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - return address; - } - return 0; -} - -/*! - \since 4.4 - Unmaps the memory \a address. - - Returns true if the unmap succeeds; false otherwise. - - \sa map() - */ -bool QFile::unmap(uchar *address) -{ - Q_D(QFile); - if (d->engine() - && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { - unsetError(); - bool success = d->fileEngine->unmap(address); - if (!success) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); - return success; - } - d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension")); - return false; -} - -/*! - Sets the file size (in bytes) \a sz. Returns true if the file if the - resize succeeds; false otherwise. If \a sz is larger than the file - currently is the new bytes will be set to 0, if \a sz is smaller the - file is simply truncated. - - \sa size(), setFileName() + \reimp */ - -bool -QFile::resize(qint64 sz) +bool QFile::resize(qint64 sz) { - Q_D(QFile); - if (!d->ensureFlushed()) - return false; - d->engine(); - if (isOpen() && d->fileEngine->pos() > sz) - seek(sz); - if(d->fileEngine->setSize(sz)) { - unsetError(); - d->cachedSize = sz; - return true; - } - d->cachedSize = 0; - d->setError(QFile::ResizeError, d->fileEngine->errorString()); - return false; + return QFileDevice::resize(sz); // for now } /*! @@ -1282,18 +1039,11 @@ QFile::resize(const QString &fileName, qint64 sz) } /*! - Returns the complete OR-ed together combination of - QFile::Permission for the file. - - \sa setPermissions(), setFileName() + \reimp */ - -QFile::Permissions -QFile::permissions() const +QFile::Permissions QFile::permissions() const { - Q_D(const QFile); - QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask; - return QFile::Permissions((int)perms); //ewww + return QFileDevice::permissions(); // for now } /*! @@ -1317,16 +1067,9 @@ QFile::permissions(const QString &fileName) \sa permissions(), setFileName() */ -bool -QFile::setPermissions(Permissions permissions) +bool QFile::setPermissions(Permissions permissions) { - Q_D(QFile); - if (d->engine()->setPermissions(permissions)) { - unsetError(); - return true; - } - d->setError(QFile::PermissionsError, d->fileEngine->errorString()); - return false; + return QFileDevice::setPermissions(permissions); // for now } /*! @@ -1341,354 +1084,12 @@ QFile::setPermissions(const QString &fileName, Permissions permissions) return QFile(fileName).setPermissions(permissions); } -static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer) -{ - qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize()); - if (ret > 0) - buffer->free(ret); - return ret; -} - -/*! - Flushes any buffered data to the file. Returns true if successful; - otherwise returns false. -*/ - -bool -QFile::flush() -{ - Q_D(QFile); - if (!d->fileEngine) { - qWarning("QFile::flush: No file engine. Is IODevice open?"); - return false; - } - - if (!d->writeBuffer.isEmpty()) { - qint64 size = d->writeBuffer.size(); - if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - } - - if (!d->fileEngine->flush()) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - return true; -} - -/*! - Calls QFile::flush() and closes the file. Errors from flush are ignored. - - \sa QIODevice::close() -*/ -void -QFile::close() -{ - Q_D(QFile); - if(!isOpen()) - return; - bool flushed = flush(); - QIODevice::close(); - - // reset write buffer - d->lastWasWrite = false; - d->writeBuffer.clear(); - - // keep earlier error from flush - if (d->fileEngine->close() && flushed) - unsetError(); - else if (flushed) - d->setError(d->fileEngine->error(), d->fileEngine->errorString()); -} - -/*! - Returns the size of the file. - - For regular empty files on Unix (e.g. those in \c /proc), this function - returns 0; the contents of such a file are generated on demand in response - to you calling read(). -*/ - -qint64 QFile::size() const -{ - Q_D(const QFile); - if (!d->ensureFlushed()) - return 0; - d->cachedSize = d->engine()->size(); - return d->cachedSize; -} - -/*! - \reimp -*/ - -qint64 QFile::pos() const -{ - return QIODevice::pos(); -} - -/*! - Returns true if the end of the file has been reached; otherwise returns - false. - - For regular empty files on Unix (e.g. those in \c /proc), this function - returns true, since the file system reports that the size of such a file is - 0. Therefore, you should not depend on atEnd() when reading data from such a - file, but rather call read() until no more data can be read. -*/ - -bool QFile::atEnd() const -{ - Q_D(const QFile); - - // If there's buffered data left, we're not at the end. - if (!d->buffer.isEmpty()) - return false; - - if (!isOpen()) - return true; - - if (!d->ensureFlushed()) - return false; - - // If the file engine knows best, say what it says. - if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) { - // Check if the file engine supports AtEndExtension, and if it does, - // check if the file engine claims to be at the end. - return d->fileEngine->atEnd(); - } - - // if it looks like we are at the end, or if size is not cached, - // fall through to bytesAvailable() to make sure. - if (pos() < d->cachedSize) - return false; - - // Fall back to checking how much is available (will stat files). - return bytesAvailable() == 0; -} - -/*! - \fn bool QFile::seek(qint64 pos) - - For random-access devices, this function sets the current position - to \a pos, returning true on success, or false if an error occurred. - For sequential devices, the default behavior is to do nothing and - return false. - - Seeking beyond the end of a file: - If the position is beyond the end of a file, then seek() shall not - immediately extend the file. If a write is performed at this position, - then the file shall be extended. The content of the file between the - previous end of file and the newly written data is UNDEFINED and - varies between platforms and file systems. -*/ - -bool QFile::seek(qint64 off) -{ - Q_D(QFile); - if (!isOpen()) { - qWarning("QFile::seek: IODevice is not open"); - return false; - } - - if (!d->ensureFlushed()) - return false; - - if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::PositionError; - d->setError(err, d->fileEngine->errorString()); - return false; - } - unsetError(); - return true; -} - -/*! - \reimp -*/ -qint64 QFile::readLineData(char *data, qint64 maxlen) -{ - Q_D(QFile); - if (!d->ensureFlushed()) - return -1; - - qint64 read; - if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) { - read = d->fileEngine->readLine(data, maxlen); - } else { - // Fall back to QIODevice's readLine implementation if the engine - // cannot do it faster. - read = QIODevice::readLineData(data, maxlen); - } - - if (read < maxlen) { - // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked - d->cachedSize = 0; - } - - return read; -} - -/*! - \reimp -*/ - -qint64 QFile::readData(char *data, qint64 len) -{ - Q_D(QFile); - unsetError(); - if (!d->ensureFlushed()) - return -1; - - qint64 read = d->fileEngine->read(data, len); - if(read < 0) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::ReadError; - d->setError(err, d->fileEngine->errorString()); - } - - if (read < len) { - // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked - d->cachedSize = 0; - } - - return read; -} - -/*! - \internal -*/ -bool QFilePrivate::putCharHelper(char c) -{ -#ifdef QT_NO_QOBJECT - return QIODevicePrivate::putCharHelper(c); -#else - - // Cutoff for code that doesn't only touch the buffer. - int writeBufferSize = writeBuffer.size(); - if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE -#ifdef Q_OS_WIN - || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE) -#endif - ) { - return QIODevicePrivate::putCharHelper(c); - } - - if (!(openMode & QIODevice::WriteOnly)) { - if (openMode == QIODevice::NotOpen) - qWarning("QIODevice::putChar: Closed device"); - else - qWarning("QIODevice::putChar: ReadOnly device"); - return false; - } - - // Make sure the device is positioned correctly. - const bool sequential = isSequential(); - if (pos != devicePos && !sequential && !q_func()->seek(pos)) - return false; - - lastWasWrite = true; - - int len = 1; -#ifdef Q_OS_WIN - if ((openMode & QIODevice::Text) && c == '\n') { - ++len; - *writeBuffer.reserve(1) = '\r'; - } -#endif - - // Write to buffer. - *writeBuffer.reserve(1) = c; - - if (!sequential) { - pos += len; - devicePos += len; - if (!buffer.isEmpty()) - buffer.skip(len); - } - - return true; -#endif -} - /*! \reimp */ - -qint64 -QFile::writeData(const char *data, qint64 len) -{ - Q_D(QFile); - unsetError(); - d->lastWasWrite = true; - bool buffered = !(d->openMode & Unbuffered); - - // Flush buffered data if this read will overflow. - if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) { - if (!flush()) - return -1; - } - - // Write directly to the engine if the block size is larger than - // the write buffer size. - if (!buffered || len > QFILE_WRITEBUFFER_SIZE) { - qint64 ret = d->fileEngine->write(data, len); - if(ret < 0) { - QFile::FileError err = d->fileEngine->error(); - if(err == QFile::UnspecifiedError) - err = QFile::WriteError; - d->setError(err, d->fileEngine->errorString()); - } - return ret; - } - - // Write to the buffer. - char *writePointer = d->writeBuffer.reserve(len); - if (len == 1) - *writePointer = *data; - else - ::memcpy(writePointer, data, len); - return len; -} - -/*! - Returns the file error status. - - The I/O device status returns an error code. For example, if open() - returns false, or a read/write operation returns -1, this function can - be called to find out the reason why the operation failed. - - \sa unsetError() -*/ - -QFile::FileError -QFile::error() const -{ - Q_D(const QFile); - return d->error; -} - -/*! - Sets the file's error to QFile::NoError. - - \sa error() -*/ -void -QFile::unsetError() +qint64 QFile::size() const { - Q_D(QFile); - d->setError(QFile::NoError); + return QFileDevice::size(); // for now } QT_END_NAMESPACE diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h index 7f370d4214..0ee8f39d95 100644 --- a/src/corelib/io/qfile.h +++ b/src/corelib/io/qfile.h @@ -42,7 +42,7 @@ #ifndef QFILE_H #define QFILE_H -#include +#include #include #include @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE class QTemporaryFile; class QFilePrivate; -class Q_CORE_EXPORT QFile : public QIODevice +class Q_CORE_EXPORT QFile : public QFileDevice { #ifndef QT_NO_QOBJECT Q_OBJECT @@ -65,39 +65,6 @@ class Q_CORE_EXPORT QFile : public QIODevice Q_DECLARE_PRIVATE(QFile) public: - - enum FileError { - NoError = 0, - ReadError = 1, - WriteError = 2, - FatalError = 3, - ResourceError = 4, - OpenError = 5, - AbortError = 6, - TimeOutError = 7, - UnspecifiedError = 8, - RemoveError = 9, - RenameError = 10, - PositionError = 11, - ResizeError = 12, - PermissionsError = 13, - CopyError = 14 - }; - - enum Permission { - ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000, - ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100, - ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010, - ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001 - }; - Q_DECLARE_FLAGS(Permissions, Permission) - - enum FileHandleFlag { - AutoCloseHandle = 0x0001, - DontCloseHandle = 0 - }; - Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag) - QFile(); QFile(const QString &name); #ifndef QT_NO_QOBJECT @@ -106,9 +73,6 @@ public: #endif ~QFile(); - FileError error() const; - void unsetError(); - QString fileName() const; void setFileName(const QString &name); @@ -141,18 +105,11 @@ public: bool copy(const QString &newName); static bool copy(const QString &fileName, const QString &newName); - bool isSequential() const; - bool open(OpenMode flags); bool open(FILE *f, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); bool open(int fd, OpenMode ioFlags, FileHandleFlags handleFlags=DontCloseHandle); - virtual void close(); qint64 size() const; - qint64 pos() const; - bool seek(qint64 offset); - bool atEnd() const; - bool flush(); bool resize(qint64 sz); static bool resize(const QString &filename, qint64 sz); @@ -162,15 +119,6 @@ public: bool setPermissions(Permissions permissionSpec); static bool setPermissions(const QString &filename, Permissions permissionSpec); - int handle() const; - - enum MemoryMapFlags { - NoOptions = 0 - }; - - uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); - bool unmap(uchar *address); - protected: #ifdef QT_NO_QOBJECT QFile(QFilePrivate &dd); @@ -178,17 +126,11 @@ protected: QFile(QFilePrivate &dd, QObject *parent = 0); #endif - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); - qint64 readLineData(char *data, qint64 maxlen); - private: friend class QTemporaryFile; Q_DISABLE_COPY(QFile) }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QFile::Permissions) - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h index 3d2d3d678b..575d7d14b9 100644 --- a/src/corelib/io/qfile_p.h +++ b/src/corelib/io/qfile_p.h @@ -53,15 +53,13 @@ // We mean it. // -#include "private/qabstractfileengine_p.h" -#include "private/qiodevice_p.h" -#include "private/qringbuffer_p.h" +#include "private/qfiledevice_p.h" QT_BEGIN_NAMESPACE class QTemporaryFile; -class QFilePrivate : public QIODevicePrivate +class QFilePrivate : public QFileDevicePrivate { Q_DECLARE_PUBLIC(QFile) friend class QTemporaryFile; @@ -76,20 +74,6 @@ protected: virtual QAbstractFileEngine *engine() const; QString fileName; - mutable QAbstractFileEngine *fileEngine; - - bool lastWasWrite; - QRingBuffer writeBuffer; - inline bool ensureFlushed() const; - - bool putCharHelper(char c); - - QFile::FileError error; - void setError(QFile::FileError err); - void setError(QFile::FileError err, const QString &errorString); - void setError(QFile::FileError err, int errNum); - - mutable qint64 cachedSize; private: static QFile::EncoderFn encoder; diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp new file mode 100644 index 0000000000..17eedb0bdd --- /dev/null +++ b/src/corelib/io/qfiledevice.cpp @@ -0,0 +1,736 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "qfiledevice.h" +#include "qfiledevice_p.h" +#include "qfsfileengine_p.h" + +#ifdef QT_NO_QOBJECT +#define tr(X) QString::fromLatin1(X) +#endif + +QT_BEGIN_NAMESPACE + +static const int QFILE_WRITEBUFFER_SIZE = 16384; + +QFileDevicePrivate::QFileDevicePrivate() + : fileEngine(0), lastWasWrite(false), + writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError), + cachedSize(0) +{ +} + +QFileDevicePrivate::~QFileDevicePrivate() +{ + delete fileEngine; + fileEngine = 0; +} + +QAbstractFileEngine * QFileDevicePrivate::engine() const +{ + if (!fileEngine) + fileEngine = new QFSFileEngine; + return fileEngine; +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err) +{ + error = err; + errorString.clear(); +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err, const QString &errStr) +{ + error = err; + errorString = errStr; +} + +void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum) +{ + error = err; + errorString = qt_error_string(errNum); +} + +/*! + \enum QFileDevice::FileError + + This enum describes the errors that may be returned by the error() + function. + + \value NoError No error occurred. + \value ReadError An error occurred when reading from the file. + \value WriteError An error occurred when writing to the file. + \value FatalError A fatal error occurred. + \value ResourceError + \value OpenError The file could not be opened. + \value AbortError The operation was aborted. + \value TimeOutError A timeout occurred. + \value UnspecifiedError An unspecified error occurred. + \value RemoveError The file could not be removed. + \value RenameError The file could not be renamed. + \value PositionError The position in the file could not be changed. + \value ResizeError The file could not be resized. + \value PermissionsError The file could not be accessed. + \value CopyError The file could not be copied. + + \omitvalue ConnectError +*/ + +/*! + \enum QFileDevice::Permission + + This enum is used by the permission() function to report the + permissions and ownership of a file. The values may be OR-ed + together to test multiple permissions and ownership values. + + \value ReadOwner The file is readable by the owner of the file. + \value WriteOwner The file is writable by the owner of the file. + \value ExeOwner The file is executable by the owner of the file. + \value ReadUser The file is readable by the user. + \value WriteUser The file is writable by the user. + \value ExeUser The file is executable by the user. + \value ReadGroup The file is readable by the group. + \value WriteGroup The file is writable by the group. + \value ExeGroup The file is executable by the group. + \value ReadOther The file is readable by anyone. + \value WriteOther The file is writable by anyone. + \value ExeOther The file is executable by anyone. + + \warning Because of differences in the platforms supported by Qt, + the semantics of ReadUser, WriteUser and ExeUser are + platform-dependent: On Unix, the rights of the owner of the file + are returned and on Windows the rights of the current user are + returned. This behavior might change in a future Qt version. + + Note that Qt does not by default check for permissions on NTFS + file systems, as this may decrease the performance of file + handling considerably. It is possible to force permission checking + on NTFS by including the following code in your source: + + \snippet doc/src/snippets/ntfsp.cpp 0 + + Permission checking is then turned on and off by incrementing and + decrementing \c qt_ntfs_permission_lookup by 1. + + \snippet doc/src/snippets/ntfsp.cpp 1 +*/ + +//************* QFileDevice + +/*! + \class QFileDevice + \since 5.0 + + \brief The QFileDevice class provides an interface for reading from and writing to open files. + + \ingroup io + + \reentrant + + QFileDevice is the base class for I/O devices that can read and write text and binary files + and \l{The Qt Resource System}{resources}. QFile offers the main functionality, + QFileDevice serves as a base class for sharing functionality with other file devices such + as QTemporaryFile, by providing all the operations that can be done on files that have + been opened by QFile or QTemporaryFile. + + \sa QFile, QTemporaryFile +*/ + +/*! + \enum QFileDevice::FileHandleFlag + + This enum is used when opening a file to specify additional + options which only apply to files and not to a generic + QIODevice. + + \value AutoCloseHandle The file handle passed into open() should be + closed by close(), the default behavior is that close just flushes + the file and the application is responsible for closing the file handle. + When opening a file by name, this flag is ignored as Qt always owns the + file handle and must close it. + \value DontCloseHandle If not explicitly closed, the underlying file + handle is left open when the QFile object is destroyed. + */ + +#ifdef QT_NO_QOBJECT +QFileDevice::QFileDevice() + : QIODevice(*new QFileDevicePrivate) +{ +} +QFileDevice::QFileDevice(QFileDevicePrivate &dd) + : QIODevice(dd) +{ +} +#else +/*! + \internal +*/ +QFileDevice::QFileDevice() + : QIODevice(*new QFileDevicePrivate, 0) +{ +} +/*! + \internal +*/ +QFileDevice::QFileDevice(QObject *parent) + : QIODevice(*new QFileDevicePrivate, parent) +{ +} +/*! + \internal +*/ +QFileDevice::QFileDevice(QFileDevicePrivate &dd, QObject *parent) + : QIODevice(dd, parent) +{ +} +#endif + +/*! + Destroys the file device, closing it if necessary. +*/ +QFileDevice::~QFileDevice() +{ + close(); +} + +/*! + Returns true if the file can only be manipulated sequentially; + otherwise returns false. + + Most files support random-access, but some special files may not. + + \sa QIODevice::isSequential() +*/ +bool QFileDevice::isSequential() const +{ + Q_D(const QFileDevice); + return d->fileEngine && d->fileEngine->isSequential(); +} + +/*! + Returns the file handle of the file. + + This is a small positive integer, suitable for use with C library + functions such as fdopen() and fcntl(). On systems that use file + descriptors for sockets (i.e. Unix systems, but not Windows) the handle + can be used with QSocketNotifier as well. + + If the file is not open, or there is an error, handle() returns -1. + + This function is not supported on Windows CE. + + \sa QSocketNotifier +*/ +int QFileDevice::handle() const +{ + Q_D(const QFileDevice); + if (!isOpen() || !d->fileEngine) + return -1; + + return d->fileEngine->handle(); +} + +/*! + Returns the name of the file. + The default implementation in QFileDevice returns QString(). +*/ +QString QFileDevice::fileName() const +{ + return QString(); +} + +static inline qint64 _qfile_writeData(QAbstractFileEngine *engine, QRingBuffer *buffer) +{ + qint64 ret = engine->write(buffer->readPointer(), buffer->nextDataBlockSize()); + if (ret > 0) + buffer->free(ret); + return ret; +} + +/*! + Flushes any buffered data to the file. Returns true if successful; + otherwise returns false. +*/ +bool QFileDevice::flush() +{ + Q_D(QFileDevice); + if (!d->fileEngine) { + qWarning("QFileDevice::flush: No file engine. Is IODevice open?"); + return false; + } + + if (!d->writeBuffer.isEmpty()) { + qint64 size = d->writeBuffer.size(); + if (_qfile_writeData(d->fileEngine, &d->writeBuffer) != size) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + } + + if (!d->fileEngine->flush()) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + return true; +} + +/*! + Calls QFileDevice::flush() and closes the file. Errors from flush are ignored. + + \sa QIODevice::close() +*/ +void QFileDevice::close() +{ + Q_D(QFileDevice); + if (!isOpen()) + return; + bool flushed = flush(); + QIODevice::close(); + + // reset write buffer + d->lastWasWrite = false; + d->writeBuffer.clear(); + + // keep earlier error from flush + if (d->fileEngine->close() && flushed) + unsetError(); + else if (flushed) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); +} + +/*! + \reimp +*/ +qint64 QFileDevice::pos() const +{ + return QIODevice::pos(); +} + +/*! + Returns true if the end of the file has been reached; otherwise returns + false. + + For regular empty files on Unix (e.g. those in \c /proc), this function + returns true, since the file system reports that the size of such a file is + 0. Therefore, you should not depend on atEnd() when reading data from such a + file, but rather call read() until no more data can be read. +*/ +bool QFileDevice::atEnd() const +{ + Q_D(const QFileDevice); + + // If there's buffered data left, we're not at the end. + if (!d->buffer.isEmpty()) + return false; + + if (!isOpen()) + return true; + + if (!d->ensureFlushed()) + return false; + + // If the file engine knows best, say what it says. + if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) { + // Check if the file engine supports AtEndExtension, and if it does, + // check if the file engine claims to be at the end. + return d->fileEngine->atEnd(); + } + + // if it looks like we are at the end, or if size is not cached, + // fall through to bytesAvailable() to make sure. + if (pos() < d->cachedSize) + return false; + + // Fall back to checking how much is available (will stat files). + return bytesAvailable() == 0; +} + +/*! + \fn bool QFileDevice::seek(qint64 pos) + + For random-access devices, this function sets the current position + to \a pos, returning true on success, or false if an error occurred. + For sequential devices, the default behavior is to do nothing and + return false. + + Seeking beyond the end of a file: + If the position is beyond the end of a file, then seek() shall not + immediately extend the file. If a write is performed at this position, + then the file shall be extended. The content of the file between the + previous end of file and the newly written data is UNDEFINED and + varies between platforms and file systems. +*/ +bool QFileDevice::seek(qint64 off) +{ + Q_D(QFileDevice); + if (!isOpen()) { + qWarning("QFileDevice::seek: IODevice is not open"); + return false; + } + + if (!d->ensureFlushed()) + return false; + + if (!d->fileEngine->seek(off) || !QIODevice::seek(off)) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::PositionError; + d->setError(err, d->fileEngine->errorString()); + return false; + } + unsetError(); + return true; +} + +/*! + \reimp +*/ +qint64 QFileDevice::readLineData(char *data, qint64 maxlen) +{ + Q_D(QFileDevice); + if (!d->ensureFlushed()) + return -1; + + qint64 read; + if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) { + read = d->fileEngine->readLine(data, maxlen); + } else { + // Fall back to QIODevice's readLine implementation if the engine + // cannot do it faster. + read = QIODevice::readLineData(data, maxlen); + } + + if (read < maxlen) { + // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked + d->cachedSize = 0; + } + + return read; +} + +/*! + \reimp +*/ +qint64 QFileDevice::readData(char *data, qint64 len) +{ + Q_D(QFileDevice); + unsetError(); + if (!d->ensureFlushed()) + return -1; + + const qint64 read = d->fileEngine->read(data, len); + if (read < 0) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::ReadError; + d->setError(err, d->fileEngine->errorString()); + } + + if (read < len) { + // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked + d->cachedSize = 0; + } + + return read; +} + +/*! + \internal +*/ +bool QFileDevicePrivate::putCharHelper(char c) +{ +#ifdef QT_NO_QOBJECT + return QIODevicePrivate::putCharHelper(c); +#else + + // Cutoff for code that doesn't only touch the buffer. + int writeBufferSize = writeBuffer.size(); + if ((openMode & QIODevice::Unbuffered) || writeBufferSize + 1 >= QFILE_WRITEBUFFER_SIZE +#ifdef Q_OS_WIN + || ((openMode & QIODevice::Text) && c == '\n' && writeBufferSize + 2 >= QFILE_WRITEBUFFER_SIZE) +#endif + ) { + return QIODevicePrivate::putCharHelper(c); + } + + if (!(openMode & QIODevice::WriteOnly)) { + if (openMode == QIODevice::NotOpen) + qWarning("QIODevice::putChar: Closed device"); + else + qWarning("QIODevice::putChar: ReadOnly device"); + return false; + } + + // Make sure the device is positioned correctly. + const bool sequential = isSequential(); + if (pos != devicePos && !sequential && !q_func()->seek(pos)) + return false; + + lastWasWrite = true; + + int len = 1; +#ifdef Q_OS_WIN + if ((openMode & QIODevice::Text) && c == '\n') { + ++len; + *writeBuffer.reserve(1) = '\r'; + } +#endif + + // Write to buffer. + *writeBuffer.reserve(1) = c; + + if (!sequential) { + pos += len; + devicePos += len; + if (!buffer.isEmpty()) + buffer.skip(len); + } + + return true; +#endif +} + +/*! + \reimp +*/ +qint64 QFileDevice::writeData(const char *data, qint64 len) +{ + Q_D(QFileDevice); + unsetError(); + d->lastWasWrite = true; + bool buffered = !(d->openMode & Unbuffered); + + // Flush buffered data if this read will overflow. + if (buffered && (d->writeBuffer.size() + len) > QFILE_WRITEBUFFER_SIZE) { + if (!flush()) + return -1; + } + + // Write directly to the engine if the block size is larger than + // the write buffer size. + if (!buffered || len > QFILE_WRITEBUFFER_SIZE) { + const qint64 ret = d->fileEngine->write(data, len); + if (ret < 0) { + QFileDevice::FileError err = d->fileEngine->error(); + if (err == QFileDevice::UnspecifiedError) + err = QFileDevice::WriteError; + d->setError(err, d->fileEngine->errorString()); + } + return ret; + } + + // Write to the buffer. + char *writePointer = d->writeBuffer.reserve(len); + if (len == 1) + *writePointer = *data; + else + ::memcpy(writePointer, data, len); + return len; +} + +/*! + Returns the file error status. + + The I/O device status returns an error code. For example, if open() + returns false, or a read/write operation returns -1, this function can + be called to find out the reason why the operation failed. + + \sa unsetError() +*/ +QFileDevice::FileError QFileDevice::error() const +{ + Q_D(const QFileDevice); + return d->error; +} + +/*! + Sets the file's error to QFileDevice::NoError. + + \sa error() +*/ +void QFileDevice::unsetError() +{ + Q_D(QFileDevice); + d->setError(QFileDevice::NoError); +} + +/*! + Returns the size of the file. + + For regular empty files on Unix (e.g. those in \c /proc), this function + returns 0; the contents of such a file are generated on demand in response + to you calling read(). +*/ +qint64 QFileDevice::size() const +{ + Q_D(const QFileDevice); + if (!d->ensureFlushed()) + return 0; + d->cachedSize = d->engine()->size(); + return d->cachedSize; +} + +/*! + Sets the file size (in bytes) \a sz. Returns true if the file if the + resize succeeds; false otherwise. If \a sz is larger than the file + currently is the new bytes will be set to 0, if \a sz is smaller the + file is simply truncated. + + \sa size() +*/ +bool QFileDevice::resize(qint64 sz) +{ + Q_D(QFileDevice); + if (!d->ensureFlushed()) + return false; + d->engine(); + if (isOpen() && d->fileEngine->pos() > sz) + seek(sz); + if (d->fileEngine->setSize(sz)) { + unsetError(); + d->cachedSize = sz; + return true; + } + d->cachedSize = 0; + d->setError(QFile::ResizeError, d->fileEngine->errorString()); + return false; +} + +/*! + Returns the complete OR-ed together combination of + QFile::Permission for the file. + + \sa setPermissions() +*/ +QFile::Permissions QFileDevice::permissions() const +{ + Q_D(const QFileDevice); + QAbstractFileEngine::FileFlags perms = d->engine()->fileFlags(QAbstractFileEngine::PermsMask) & QAbstractFileEngine::PermsMask; + return QFile::Permissions((int)perms); //ewww +} + +/*! + Sets the permissions for the file to the \a permissions specified. + Returns true if successful, or false if the permissions cannot be + modified. + + \sa permissions() +*/ +bool QFileDevice::setPermissions(Permissions permissions) +{ + Q_D(QFileDevice); + if (d->engine()->setPermissions(permissions)) { + unsetError(); + return true; + } + d->setError(QFile::PermissionsError, d->fileEngine->errorString()); + return false; +} + +/*! + \enum QFileDevice::MemoryMapFlags + \since 4.4 + + This enum describes special options that may be used by the map() + function. + + \value NoOptions No options. +*/ + +/*! + Maps \a size bytes of the file into memory starting at \a offset. A file + should be open for a map to succeed but the file does not need to stay + open after the memory has been mapped. When the QFile is destroyed + or a new file is opened with this object, any maps that have not been + unmapped will automatically be unmapped. + + Any mapping options can be passed through \a flags. + + Returns a pointer to the memory or 0 if there is an error. + + \note On Windows CE 5.0 the file will be closed before mapping occurs. + + \sa unmap() + */ +uchar *QFileDevice::map(qint64 offset, qint64 size, MemoryMapFlags flags) +{ + Q_D(QFileDevice); + if (d->engine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::MapExtension)) { + unsetError(); + uchar *address = d->fileEngine->map(offset, size, flags); + if (address == 0) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + return address; + } + return 0; +} + +/*! + Unmaps the memory \a address. + + Returns true if the unmap succeeds; false otherwise. + + \sa map() + */ +bool QFileDevice::unmap(uchar *address) +{ + Q_D(QFileDevice); + if (d->engine() + && d->fileEngine->supportsExtension(QAbstractFileEngine::UnMapExtension)) { + unsetError(); + bool success = d->fileEngine->unmap(address); + if (!success) + d->setError(d->fileEngine->error(), d->fileEngine->errorString()); + return success; + } + d->setError(PermissionsError, tr("No file engine available or engine does not support UnMapExtension")); + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h new file mode 100644 index 0000000000..bbde91842c --- /dev/null +++ b/src/corelib/io/qfiledevice.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILEDEVICE_H +#define QFILEDEVICE_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QFileDevicePrivate; + +class Q_CORE_EXPORT QFileDevice : public QIODevice +{ +#ifndef QT_NO_QOBJECT + Q_OBJECT +#endif + Q_DECLARE_PRIVATE(QFileDevice) + +public: + enum FileError { + NoError = 0, + ReadError = 1, + WriteError = 2, + FatalError = 3, + ResourceError = 4, + OpenError = 5, + AbortError = 6, + TimeOutError = 7, + UnspecifiedError = 8, + RemoveError = 9, + RenameError = 10, + PositionError = 11, + ResizeError = 12, + PermissionsError = 13, + CopyError = 14 + }; + + enum Permission { + ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000, + ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100, + ReadGroup = 0x0040, WriteGroup = 0x0020, ExeGroup = 0x0010, + ReadOther = 0x0004, WriteOther = 0x0002, ExeOther = 0x0001 + }; + Q_DECLARE_FLAGS(Permissions, Permission) + + enum FileHandleFlag { + AutoCloseHandle = 0x0001, + DontCloseHandle = 0 + }; + Q_DECLARE_FLAGS(FileHandleFlags, FileHandleFlag) + + ~QFileDevice(); + + FileError error() const; + void unsetError(); + + virtual void close(); + + bool isSequential() const; + + int handle() const; + virtual QString fileName() const; + + qint64 pos() const; + bool seek(qint64 offset); + bool atEnd() const; + bool flush(); + + qint64 size() const; + + virtual bool resize(qint64 sz); + virtual Permissions permissions() const; + virtual bool setPermissions(Permissions permissionSpec); + + enum MemoryMapFlags { + NoOptions = 0 + }; + + uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions); + bool unmap(uchar *address); + +protected: + QFileDevice(); +#ifdef QT_NO_QOBJECT + QFileDevice(QFileDevicePrivate &dd); +#else + explicit QFileDevice(QObject *parent); + QFileDevice(QFileDevicePrivate &dd, QObject *parent = 0); +#endif + + qint64 readData(char *data, qint64 maxlen); + qint64 writeData(const char *data, qint64 len); + qint64 readLineData(char *data, qint64 maxlen); + +private: + Q_DISABLE_COPY(QFileDevice) +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QFileDevice::Permissions) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFILEDEVICE_H diff --git a/src/corelib/io/qfiledevice_p.h b/src/corelib/io/qfiledevice_p.h new file mode 100644 index 0000000000..2550cd73a2 --- /dev/null +++ b/src/corelib/io/qfiledevice_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QFILEDEVICE_P_H +#define QFILEDEVICE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qiodevice_p.h" +#include "private/qringbuffer_p.h" + +QT_BEGIN_NAMESPACE + +class QAbstractFileEngine; +class QFSFileEngine; + +class QFileDevicePrivate : public QIODevicePrivate +{ + Q_DECLARE_PUBLIC(QFileDevice) +protected: + QFileDevicePrivate(); + ~QFileDevicePrivate(); + + virtual QAbstractFileEngine *engine() const; + + QFileDevice::FileHandleFlags handleFlags; + + mutable QAbstractFileEngine *fileEngine; + bool lastWasWrite; + QRingBuffer writeBuffer; + inline bool ensureFlushed() const; + + bool putCharHelper(char c); + + QFileDevice::FileError error; + void setError(QFileDevice::FileError err); + void setError(QFileDevice::FileError err, const QString &errorString); + void setError(QFileDevice::FileError err, int errNum); + + mutable qint64 cachedSize; +}; + +inline bool QFileDevicePrivate::ensureFlushed() const +{ + // This function ensures that the write buffer has been flushed (const + // because certain const functions need to call it. + if (lastWasWrite) { + const_cast(this)->lastWasWrite = false; + if (!const_cast(q_func())->flush()) + return false; + } + return true; +} + +QT_END_NAMESPACE + +#endif // QFILEDEVICE_P_H diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 1d641d2301..571bae7f24 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -67,6 +67,7 @@ SOURCES += \ ../../corelib/io/qfsfileengine.cpp \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ + ../../corelib/io/qfiledevice.cpp \ ../../corelib/io/qtemporaryfile.cpp \ ../../corelib/io/qtextstream.cpp \ ../../corelib/io/qurl.cpp \ diff --git a/tools/configure/Makefile.mingw b/tools/configure/Makefile.mingw index 086dd71a85..ce923db5bc 100644 --- a/tools/configure/Makefile.mingw +++ b/tools/configure/Makefile.mingw @@ -36,6 +36,7 @@ OBJECTS = \ qdatastream.o \ qdir.o \ qdiriterator.o \ + qfiledevice.o \ qfile.o \ qfileinfo.o \ qabstractfileengine.o \ diff --git a/tools/configure/Makefile.win32 b/tools/configure/Makefile.win32 index d2193d7619..57fe6726c2 100644 --- a/tools/configure/Makefile.win32 +++ b/tools/configure/Makefile.win32 @@ -34,6 +34,7 @@ OBJECTS = \ qdatastream.obj \ qdir.obj \ qdiriterator.obj \ + qfiledevice.obj \ qfile.obj \ qfileinfo.obj \ qabstractfileengine.obj \ @@ -103,6 +104,7 @@ qbuffer.obj: $(CORESRC)\io\qbuffer.cpp $(PCH) qdatastream.obj: $(CORESRC)\io\qdatastream.cpp $(PCH) qdir.obj: $(CORESRC)\io\qdir.cpp $(PCH) qdiriterator.obj: $(CORESRC)\io\qdiriterator.cpp $(PCH) +qfiledevice.obj: $(CORESRC)\io\qfiledevice.cpp $(PCH) qfile.obj: $(CORESRC)\io\qfile.cpp $(PCH) qfileinfo.obj: $(CORESRC)\io\qfileinfo.cpp $(PCH) qabstractfileengine.obj: $(CORESRC)\io\qabstractfileengine.cpp $(PCH) diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index b0224891c3..8aa45bebb4 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -48,6 +48,7 @@ HEADERS = configureapp.h environment.h tools.h\ $$QT_SOURCE_TREE/src/corelib/io/qdatastream.h \ $$QT_SOURCE_TREE/src/corelib/io/qdir.h \ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.h \ + $$QT_SOURCE_TREE/src/corelib/io/qfiledevice.h \ $$QT_SOURCE_TREE/src/corelib/io/qfile.h \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.h \ $$QT_SOURCE_TREE/src/corelib/io/qfilesystementry_p.h \ @@ -92,6 +93,7 @@ SOURCES = main.cpp configureapp.cpp environment.cpp tools.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdatastream.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdir.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qdiriterator.cpp \ + $$QT_SOURCE_TREE/src/corelib/io/qfiledevice.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfile.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qfileinfo.cpp \ $$QT_SOURCE_TREE/src/corelib/io/qabstractfileengine.cpp \ -- cgit v1.2.3 From c78957766a5adba45289a0f7afe22949a183b34b Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 2 Mar 2012 20:33:55 +0100 Subject: QMimeDatabase: Fix crash on empty filename This is due to the search in the suffix tree starting at position fileName.length() - 1. Change-Id: I98501c1724c7dde2626351ace8ba19faa0d2e1e1 Reviewed-by: Ivan Komissarov Reviewed-by: Wolf-Michael Bolle --- src/corelib/mimetypes/qmimeprovider.cpp | 2 ++ tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 8ef0ee8881..0c2f25a1f9 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -283,6 +283,8 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name) QStringList QMimeBinaryProvider::findByFileName(const QString &fileName, QString *foundSuffix) { checkCache(); + if (fileName.isEmpty()) + return QStringList(); const QString lowerFileName = fileName.toLower(); QMimeGlobMatchResult result; // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly. diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 63adcadb86..9076f37c7c 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -207,6 +207,7 @@ void tst_QMimeDatabase::mimeTypeForFileName_data() QTest::newRow("directory") << "/" << "inode/directory"; QTest::newRow("doesn't exist, no extension") << "IDontExist" << "application/octet-stream"; QTest::newRow("doesn't exist but has known extension") << "IDontExist.txt" << "text/plain"; + QTest::newRow("empty") << "" << "application/octet-stream"; } static inline QByteArray msgMimeTypeForFileNameFailed(const QList &actual, -- cgit v1.2.3 From 00821ec710ec8d9549b9f7e68837a7393a954754 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 29 Feb 2012 15:53:24 +0000 Subject: QSslCertificate - make lazy initialisation thread safe QSslCertificate can be copied around into multiple threads, without detaching. For example, the https worker threads inside QNetworkAccessManager. There are const methods, which lazily initialise members of the private class without detaching (i.e. caching results of expensive function calls) These functions now lock the d pointer using QMutexPool to avoid concurrency related crashes. autotest crashes 20% of the time in release builds without the fix, passes 100 times in a row with the fix. Task-number: QTBUG-20452 Change-Id: I64a01af8159216f2dd6215a08669890f6c029ca8 Reviewed-by: Thiago Macieira Reviewed-by: Richard J. Moore --- src/network/ssl/qsslcertificate.cpp | 9 +++ .../ssl/qsslcertificate/tst_qsslcertificate.cpp | 72 ++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 966497be2e..a9573bf1d8 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -123,6 +123,7 @@ #include #include #include +#include #include #include #include @@ -263,6 +264,7 @@ void QSslCertificate::clear() */ QByteArray QSslCertificate::version() const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); if (d->versionString.isEmpty() && d->x509) d->versionString = QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1); @@ -275,6 +277,7 @@ QByteArray QSslCertificate::version() const */ QByteArray QSslCertificate::serialNumber() const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); if (d->serialNumberString.isEmpty() && d->x509) { ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber; QByteArray hexString; @@ -327,6 +330,7 @@ static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) */ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = @@ -344,6 +348,7 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const */ QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = @@ -363,6 +368,7 @@ QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const */ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = @@ -379,6 +385,7 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const */ QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = @@ -398,6 +405,7 @@ QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const */ QList QSslCertificate::subjectInfoAttributes() const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = @@ -417,6 +425,7 @@ QList QSslCertificate::subjectInfoAttributes() const */ QList QSslCertificate::issuerInfoAttributes() const { + QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index 5da9ff0476..93299c26c6 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -109,6 +109,7 @@ private slots: void subjectAndIssuerAttributes(); void verify(); void extensions(); + void threadSafeConstMethods(); // helper for verbose test failure messages QString toString(const QList&); @@ -1059,6 +1060,77 @@ void tst_QSslCertificate::extensions() } +class TestThread : public QThread +{ +public: + void run() + { + effectiveDate = cert.effectiveDate(); + expiryDate = cert.expiryDate(); + extensions = cert.extensions(); + isBlacklisted = cert.isBlacklisted(); + issuerInfo = cert.issuerInfo(QSslCertificate::CommonName); + issuerInfoAttributes = cert.issuerInfoAttributes(); + publicKey = cert.publicKey(); + serialNumber = cert.serialNumber(); + subjectInfo = cert.subjectInfo(QSslCertificate::CommonName); + subjectInfoAttributes = cert.subjectInfoAttributes(); + toDer = cert.toDer(); + toPem = cert.toPem(); + toText = cert.toText(); + version = cert.version(); + } + QSslCertificate cert; + QDateTime effectiveDate; + QDateTime expiryDate; + QList extensions; + bool isBlacklisted; + QStringList issuerInfo; + QList issuerInfoAttributes; + QSslKey publicKey; + QByteArray serialNumber; + QStringList subjectInfo; + QList subjectInfoAttributes; + QByteArray toDer; + QByteArray toPem; + QByteArray toText; + QByteArray version; +}; + +void tst_QSslCertificate::threadSafeConstMethods() +{ + if (!QSslSocket::supportsSsl()) + return; + + QByteArray encoded = readFile(testDataDir + "/certificates/cert.pem"); + QSslCertificate certificate(encoded); + QVERIFY(!certificate.isNull()); + + TestThread t1; + t1.cert = certificate; //shallow copy + TestThread t2; + t2.cert = certificate; //shallow copy + t1.start(); + t2.start(); + QVERIFY(t1.wait(5000)); + QVERIFY(t2.wait(5000)); + QVERIFY(t1.cert == t2.cert); + QVERIFY(t1.effectiveDate == t2.effectiveDate); + QVERIFY(t1.expiryDate == t2.expiryDate); + //QVERIFY(t1.extensions == t2.extensions); // no equality operator, so not tested + QVERIFY(t1.isBlacklisted == t2.isBlacklisted); + QVERIFY(t1.issuerInfo == t2.issuerInfo); + QVERIFY(t1.issuerInfoAttributes == t2.issuerInfoAttributes); + QVERIFY(t1.publicKey == t2.publicKey); + QVERIFY(t1.serialNumber == t2.serialNumber); + QVERIFY(t1.subjectInfo == t2.subjectInfo); + QVERIFY(t1.subjectInfoAttributes == t2.subjectInfoAttributes); + QVERIFY(t1.toDer == t2.toDer); + QVERIFY(t1.toPem == t2.toPem); + QVERIFY(t1.toText == t2.toText); + QVERIFY(t1.version == t2.version); + +} #endif // QT_NO_SSL -- cgit v1.2.3 From 52843c1988aaf9be8f255a340f5f21c20489de42 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 24 Feb 2012 17:53:30 +0100 Subject: de-duplicate feature and mkspec root candidate lists Change-Id: I03f5b5903a133e5386b9ebef640ddbacdf3ebcd4 Reviewed-by: Joerg Bornemann --- qmake/option.cpp | 1 + qmake/project.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/qmake/option.cpp b/qmake/option.cpp index 4e0d5b198e..3fc66a8f3d 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -595,6 +595,7 @@ QStringList Option::mkspecPaths() if (!Option::mkfile::project_root.isEmpty()) ret << Option::mkfile::project_root + concat; ret << QLibraryInfo::location(QLibraryInfo::HostDataPath) + concat; + ret.removeDuplicates(); return ret; } diff --git a/qmake/project.cpp b/qmake/project.cpp index 35aaee9775..a9e99e4b79 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -593,6 +593,7 @@ QStringList qmake_feature_paths(QMakeProperty *prop=0) concat_it != concat.end(); ++concat_it) feature_roots << (QLibraryInfo::location(QLibraryInfo::HostDataPath) + mkspecs_concat + (*concat_it)); + feature_roots.removeDuplicates(); return feature_roots; } -- cgit v1.2.3 From 9d5e721e96f19812a766a4c7d3f8b41f455f507c Mon Sep 17 00:00:00 2001 From: Max Desyatov Date: Fri, 2 Mar 2012 13:33:17 +0200 Subject: escape *_script_file usages in MingwMakefileGenerator::writeObjectsPart Task-number: QTBUG-24595 Change-Id: I1e78a6015247b9e41ae2b05b50fdedf0613f00f1 Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/mingw_make.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index 03460551a9..c088e8e480 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -404,14 +404,14 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t) QString ar_cmd = project->values("QMAKE_LIB").join(" "); if (ar_cmd.isEmpty()) ar_cmd = "armar --create"; - objectsLinkLine = ar_cmd + " " + var("DEST_TARGET") + " --via " + ar_script_file; + objectsLinkLine = ar_cmd + " " + var("DEST_TARGET") + " --via " + escapeFilePath(ar_script_file); } else { // Strip off any options since the ar commands will be read from file. QString ar_cmd = var("QMAKE_LIB").section(" ", 0, 0);; if (ar_cmd.isEmpty()) ar_cmd = "ar"; createArObjectScriptFile(ar_script_file, var("DEST_TARGET"), project->values("OBJECTS")); - objectsLinkLine = ar_cmd + " -M < " + ar_script_file; + objectsLinkLine = ar_cmd + " -M < " + escapeFilePath(ar_script_file); } } else { QString ld_script_file = var("QMAKE_LINK_OBJECT_SCRIPT") + "." + var("TARGET"); @@ -420,10 +420,10 @@ void MingwMakefileGenerator::writeObjectsPart(QTextStream &t) } if (project->isActiveConfig("rvct_linker")) { createRvctObjectScriptFile(ld_script_file, project->values("OBJECTS")); - objectsLinkLine = QString::fromLatin1("--via ") + ld_script_file; + objectsLinkLine = QString::fromLatin1("--via ") + escapeFilePath(ld_script_file); } else { createLdObjectScriptFile(ld_script_file, project->values("OBJECTS")); - objectsLinkLine = ld_script_file; + objectsLinkLine = escapeFilePath(ld_script_file); } } Win32MakefileGenerator::writeObjectsPart(t); -- cgit v1.2.3 From 930a90d97835223587c2c8df1213c64295f3af97 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Fri, 24 Feb 2012 09:17:00 +0100 Subject: Cocoa: Implement widget palettes. Add roles to QPLatformTheme::Palette, map QWidget subclasses to those. Port Qt4 widget palette creation code to use the QPLatformTheme::Palette roles. Palette entries are disabled in this commit, this will be fixed later. Change-Id: I07babe3d7c76d306efc4ea4813c7161fdf36227f Reviewed-by: Friedemann Kleint --- src/gui/kernel/qplatformtheme_qpa.h | 13 ++++ src/plugins/platforms/cocoa/qcocoasystemsettings.h | 4 +- .../platforms/cocoa/qcocoasystemsettings.mm | 86 +++++++++++++++++++++- src/plugins/platforms/cocoa/qcocoatheme.h | 4 +- src/plugins/platforms/cocoa/qcocoatheme.mm | 5 +- src/widgets/kernel/qapplication.cpp | 5 +- src/widgets/kernel/qapplication_qpa.cpp | 25 +++++++ 7 files changed, 136 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qplatformtheme_qpa.h b/src/gui/kernel/qplatformtheme_qpa.h index 3610a3c1c8..be18e4fe38 100644 --- a/src/gui/kernel/qplatformtheme_qpa.h +++ b/src/gui/kernel/qplatformtheme_qpa.h @@ -86,6 +86,19 @@ public: enum Palette { SystemPalette, ToolTipPalette, + ToolButtonPalette, + ButtonPalette, + HeaderPalette, + ComboBoxPalette, + ItemViewPalette, + MessageBoxLabelPelette, + TabBarPalette, + LabelPalette, + GroupBoxPalette, + MenuPalette, + MenuBarPalette, + TextEditPalette, + TextLineEditPalette, NPalettes }; diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.h b/src/plugins/platforms/cocoa/qcocoasystemsettings.h index 84a66d7193..2ed6f766aa 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.h +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.h @@ -42,12 +42,14 @@ #ifndef QCOCOASYSTEMSETTINGS_H #define QCOCOASYSTEMSETTINGS_H -#include +#include #include +#include QT_BEGIN_NAMESPACE QPalette * qt_mac_createSystemPalette(); +QHash qt_mac_createRolePalettes(); QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 5170c0bc8a..eea2fb6f5d 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -41,9 +41,10 @@ #include "qcocoasystemsettings.h" -#include #include +#include + QColor qt_mac_colorFromCGColor(CGColorRef cgcolor) { QColor pc; @@ -143,3 +144,86 @@ QPalette * qt_mac_createSystemPalette() return palette; } + +struct QMacPaletteMap { + inline QMacPaletteMap(QPlatformTheme::Palette p, ThemeBrush a, ThemeBrush i) : + paletteRole(p), active(a), inactive(i) { } + + QPlatformTheme::Palette paletteRole; + ThemeBrush active, inactive; +}; + +static QMacPaletteMap mac_widget_colors[] = { +// TODO (msorvig): Fix/match palette behavior with Qt 4 and enable. +// +// QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive), +// QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), +// QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive), +// QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive), +// QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive), +// QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive), +// QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive), +// QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), +// QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive), +// QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive), +// ### TODO: The zeros below gives white-on-black text. +// QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0), +// QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0), + QMacPaletteMap(QPlatformTheme::NPalettes, 0, 0) }; + +QHash qt_mac_createRolePalettes() +{ + QHash palettes; + QColor qc; + for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) { + QPalette pal; + if (mac_widget_colors[i].active != 0) { + qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active); + pal.setColor(QPalette::Active, QPalette::Text, qc); + pal.setColor(QPalette::Active, QPalette::WindowText, qc); + pal.setColor(QPalette::Active, QPalette::HighlightedText, qc); + qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].inactive); + pal.setColor(QPalette::Inactive, QPalette::Text, qc); + pal.setColor(QPalette::Disabled, QPalette::Text, qc); + pal.setColor(QPalette::Inactive, QPalette::WindowText, qc); + pal.setColor(QPalette::Disabled, QPalette::WindowText, qc); + pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc); + pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc); + } + if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette) { + qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive); + pal.setBrush(QPalette::ButtonText, qc); + qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected); + pal.setBrush(QPalette::HighlightedText, qc); + qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemDisabled); + pal.setBrush(QPalette::Disabled, QPalette::Text, qc); + } else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette) + || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)) { + pal.setColor(QPalette::Disabled, QPalette::ButtonText, + pal.color(QPalette::Disabled, QPalette::Text)); + pal.setColor(QPalette::Inactive, QPalette::ButtonText, + pal.color(QPalette::Inactive, QPalette::Text)); + pal.setColor(QPalette::Active, QPalette::ButtonText, + pal.color(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) { + pal.setBrush(QPalette::Active, QPalette::Highlight, + qt_mac_colorForTheme(kThemeBrushAlternatePrimaryHighlightColor)); + qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected); + pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc); + pal.setBrush(QPalette::Inactive, QPalette::Text, + pal.brush(QPalette::Active, QPalette::Text)); + pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, + pal.brush(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) { + pal.setBrush(QPalette::Inactive, QPalette::Text, + pal.brush(QPalette::Active, QPalette::Text)); + pal.setBrush(QPalette::Inactive, QPalette::HighlightedText, + pal.brush(QPalette::Active, QPalette::Text)); + } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette) { + pal.setBrush(QPalette::Disabled, QPalette::Base, + pal.brush(QPalette::Active, QPalette::Base)); + } + palettes.insert(mac_widget_colors[i].paletteRole, new QPalette(pal)); + } + return palettes; +} diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index fa235b6be0..dccda2ce3b 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -42,8 +42,7 @@ #ifndef QPLATFORMTHEME_COCOA_H #define QPLATFORMTHEME_COCOA_H -#include - +#include #include QT_BEGIN_NAMESPACE @@ -66,6 +65,7 @@ public: QVariant themeHint(ThemeHint hint) const; private: mutable QPalette *m_systemPalette; + mutable QHash m_palettes; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 6b0e04acf8..71d7c9e294 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -109,8 +109,11 @@ const QPalette *QCocoaTheme::palette(Palette type) const if (type == SystemPalette) { if (!m_systemPalette) m_systemPalette = qt_mac_createSystemPalette(); - return m_systemPalette; + } else { + if (m_palettes.isEmpty()) + m_palettes = qt_mac_createRolePalettes(); + return m_palettes.value(type, 0); } return 0; } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 53f4942310..bf2729a6d8 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -131,8 +131,11 @@ QApplicationPrivate *QApplicationPrivate::self = 0; static void initSystemPalette() { if (!QApplicationPrivate::sys_pal) - if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette()) + if (const QPalette *themePalette = QGuiApplicationPrivate::platformTheme()->palette()) { QApplicationPrivate::setSystemPalette(*themePalette); + QApplicationPrivate::initializeWidgetPaletteHash(); + } + if (!QApplicationPrivate::sys_pal && QApplicationPrivate::app_style) QApplicationPrivate::setSystemPalette(QApplicationPrivate::app_style->standardPalette()); } diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index 54c5c39396..6c91b89674 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -289,8 +289,33 @@ void QApplicationPrivate::cleanupMultitouch_sys() { } +static void setPossiblePalette(const QPalette *palette, const char *className) +{ + if (palette == 0) + return; + QApplicationPrivate::setPalette_helper(*palette, className, false); +} + + void QApplicationPrivate::initializeWidgetPaletteHash() { + QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme(); + if (!platformTheme) + return; + setPossiblePalette(platformTheme->palette(QPlatformTheme::ToolButtonPalette), "QToolButton"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::ButtonPalette), "QAbstractButton"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "QHeaderView"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::HeaderPalette), "Q3Header"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::ItemViewPalette), "QAbstractItemView"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::MessageBoxLabelPelette), "QMessageBoxLabel"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::TabBarPalette), "QTabBar"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::LabelPalette), "QLabel"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::GroupBoxPalette), "QGroupBox"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuPalette), "QMenu"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::MenuBarPalette), "QMenuBar"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextEdit"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::TextEditPalette), "QTextControl"); + setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit"); } #ifndef QT_NO_WHEELEVENT -- cgit v1.2.3 From e5dabe8338cb3dacf24079e315e07f2705fd0a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Mon, 5 Mar 2012 15:40:03 +0100 Subject: Improve safeness of QMetaType::registerType. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This internal function is abused by some modules to create dynamic types in metatype system. In Qt5 more non-optional arguments were added to the function and to keep temporary source compatibility an overload was created. QMetaType code assumes that every known type has properly defined basic operations like creation and destruction. Setting a helper function pointer to null value is asking for a crash, because the code doesn't check for that value, the null pointer may be called. Change-Id: I5ca7454a70c308e01de26fab23481b3c94c22371 Reviewed-by: João Abecasis --- src/corelib/kernel/qmetatype.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 003ad1c32d..410a5cc712 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -456,7 +456,7 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length) int QMetaType::registerType(const char *typeName, Deleter deleter, Creator creator) { - return registerType(typeName, deleter, creator, 0, 0, 0, TypeFlags()); + return registerType(typeName, deleter, creator, qMetaTypeDestructHelper, qMetaTypeConstructHelper, 0, TypeFlags()); } /*! \internal @@ -474,7 +474,7 @@ int QMetaType::registerType(const char *typeName, Deleter deleter, int size, TypeFlags flags) { QVector *ct = customTypes(); - if (!ct || !typeName || !deleter || !creator) + if (!ct || !typeName || !deleter || !creator || !destructor || !constructor) return -1; #ifdef QT_NO_QOBJECT @@ -1331,6 +1331,7 @@ private: return; deleter = ct->at(type - QMetaType::User).deleter; } + Q_ASSERT_X(deleter, "void QMetaType::destroy(int type, void *data)", "The type was not properly registered"); deleter(where); } @@ -1393,6 +1394,7 @@ private: return 0; ctor = ct->at(type - QMetaType::User).constructor; } + Q_ASSERT_X(ctor, "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered"); return ctor(where, copy); } @@ -1481,6 +1483,7 @@ private: return; dtor = ct->at(type - QMetaType::User).destructor; } + Q_ASSERT_X(dtor, "void QMetaType::destruct(int type, void *where)", "The type was not properly registered"); dtor(where); } -- cgit v1.2.3 From 9f13a7d020749e936dfe0b4c0a1d46f4dbee810f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 2 Mar 2012 16:20:55 +0100 Subject: Make cache of opentype tables in Harfbuzz face lazy The mechanism in fontconfig which determines if a certain character is available (FcCharSetHasChar()) may give false positives, in which case we would load and unload those fonts per every char for which FC gave us a false positive. This was a major performance regression. Specifically the false positives happened when looking at e.g. italic variants of certain multilingual fonts, since we only check the charset of the font family as a whole and not of the specific variant, which may only support a subset of the chars. To optimize this, we remove the deletion of the font engines after loading them, but also wait with loading the opentype tables until they are actually needed. This means that for the false positives, we will load the font, but the cached data for each unused font will be much smaller. Change-Id: Idfc794401a2080da5946bf65204eb947aeb635ed Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp | 26 +++++++++++++++++++++++++- src/3rdparty/harfbuzz/src/harfbuzz-shaper.h | 8 +++++++- src/corelib/tools/qharfbuzz.cpp | 7 ++++++- src/corelib/tools/qharfbuzz_p.h | 1 + src/gui/text/qfontengine.cpp | 15 ++++++++++----- src/gui/text/qfontengine_p.h | 1 + src/gui/text/qtextengine.cpp | 2 +- 7 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp index af0ee52e9a..f6900325bc 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp +++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp @@ -995,7 +995,7 @@ static HB_Stream getTableStream(void *font, HB_GetFontTableFunc tableFunc, HB_Ta return stream; } -HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) +HB_Face HB_AllocFace(void *font, HB_GetFontTableFunc tableFunc) { HB_Face face = (HB_Face )malloc(sizeof(HB_FaceRec)); if (!face) @@ -1012,6 +1012,30 @@ HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) face->tmpLogClusters = 0; face->glyphs_substituted = false; face->buffer = 0; + face->font_for_init = font; + face->get_font_table_func = tableFunc; + + return face; +} + +HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc) +{ + HB_Face face = HB_AllocFace(font, tableFunc); + if (face) + face = HB_LoadFace(face); + return face; +} + +HB_Face HB_LoadFace(HB_Face face) +{ + void *font = face->font_for_init; + if (!font) + return face; + + HB_GetFontTableFunc tableFunc = face->get_font_table_func; + + face->get_font_table_func = 0; + face->font_for_init = 0; HB_Error error = HB_Err_Ok; HB_Stream stream; diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h index 470e27b6f9..f225a86525 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h +++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h @@ -201,6 +201,8 @@ typedef struct { hb_bitfield combiningClass :8; } HB_GlyphAttributes; +typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length); + typedef struct HB_FaceRec_ { HB_Bool isSymbolFont; @@ -217,11 +219,15 @@ typedef struct HB_FaceRec_ { unsigned int *tmpLogClusters; int length; int orig_nglyphs; + void *font_for_init; + HB_GetFontTableFunc get_font_table_func; } HB_FaceRec; -typedef HB_Error (*HB_GetFontTableFunc)(void *font, HB_Tag tag, HB_Byte *buffer, HB_UInt *length); + HB_Face HB_NewFace(void *font, HB_GetFontTableFunc tableFunc); +HB_Face HB_AllocFace(void *font, HB_GetFontTableFunc tableFunc); +HB_Face HB_LoadFace(HB_Face face); void HB_FreeFace(HB_Face face); typedef struct { diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp index 7d08547ab8..11126b814d 100644 --- a/src/corelib/tools/qharfbuzz.cpp +++ b/src/corelib/tools/qharfbuzz.cpp @@ -122,7 +122,12 @@ HB_Bool qShapeItem(HB_ShaperItem *item) HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc) { - return HB_NewFace(font, tableFunc); + return HB_AllocFace(font, tableFunc); +} + +HB_Face qHBLoadFace(HB_Face face) +{ + return HB_LoadFace(face); } void qHBFreeFace(HB_Face face) diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h index cc575ddffa..3cef3a55dd 100644 --- a/src/corelib/tools/qharfbuzz_p.h +++ b/src/corelib/tools/qharfbuzz_p.h @@ -68,6 +68,7 @@ Q_CORE_EXPORT HB_Bool qShapeItem(HB_ShaperItem *item); // ### temporary Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc); Q_CORE_EXPORT void qHBFreeFace(HB_Face); +Q_CORE_EXPORT HB_Face qHBLoadFace(HB_Face face); Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 4bceb28ef7..142d627100 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -227,6 +227,15 @@ HB_Face QFontEngine::harfbuzzFace() const return hbFace; } +HB_Face QFontEngine::initializedHarfbuzzFace() const +{ + HB_Face face = harfbuzzFace(); + if (face != 0 && face->font_for_init != 0) + face = qHBLoadFace(face); + + return face; +} + glyph_metrics_t QFontEngine::boundingBox(glyph_t glyph, const QTransform &matrix) { glyph_metrics_t metrics = boundingBox(glyph); @@ -1364,15 +1373,13 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, if (glyphs->glyphs[glyph_pos] == 0 && str[i].category() != QChar::Separator_Line) { QGlyphLayoutInstance tmp = glyphs->instance(glyph_pos); for (int x=1; x < engines.size(); ++x) { - if (!shouldLoadFontEngineForCharacter(x, ucs4)) + if (engines.at(x) == 0 && !shouldLoadFontEngineForCharacter(x, ucs4)) continue; QFontEngine *engine = engines.at(x); - bool deleteThisEngine = false; if (!engine) { const_cast(this)->loadEngine(x); engine = engines.at(x); - deleteThisEngine = true; } Q_ASSERT(engine != 0); if (engine->type() == Box) @@ -1388,8 +1395,6 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, // set the high byte to indicate which engine the glyph came from glyphs->glyphs[glyph_pos] |= (x << 24); break; - } else if (deleteThisEngine) { - const_cast(this)->unloadEngine(x); } } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 44464ee788..660e3be459 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -235,6 +235,7 @@ public: HB_Font harfbuzzFont() const; HB_Face harfbuzzFace() const; + HB_Face initializedHarfbuzzFace() const; virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 0460db14d5..dae02def07 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1112,7 +1112,7 @@ void QTextEngine::shapeTextWithHarfbuzz(int item) const si.leading = qMax(actualFontEngine->leading(), si.leading); shaper_item.font = actualFontEngine->harfbuzzFont(); - shaper_item.face = actualFontEngine->harfbuzzFace(); + shaper_item.face = actualFontEngine->initializedHarfbuzzFace(); shaper_item.glyphIndicesPresent = true; -- cgit v1.2.3 From 9a5c728e4664cdd22ab999a9c7c15b7ed4965ce1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Mar 2012 08:42:54 +0100 Subject: QStateMachine: make ctor explicit Change-Id: I727129b52daeb0d54685d530f034d41896d1da0f Reviewed-by: Stephen Kelly --- src/corelib/statemachine/qstatemachine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index c9c60976d1..b3aeb41016 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -119,7 +119,7 @@ public: NoCommonAncestorForTransitionError }; - QStateMachine(QObject *parent = 0); + explicit QStateMachine(QObject *parent = 0); ~QStateMachine(); void addState(QAbstractState *state); -- cgit v1.2.3 From eb24dfcccb304c84a147f0eafd3b3fc3df3ef4f3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 2 Mar 2012 14:48:09 +0100 Subject: Add template specialization of QMetaType for QObject derived pointers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it possible to do things like QVariant::fromValue(new SomeObject); without first using Q_DECLARE_METATYPE(Something*) This functionality was originally part of http://codereview.qt-project.org/#change,11710 but was rejected because the functionality was based on specialization of QVariant::fromValue which could be dangerous. This new implementation doesn't have such danger. Change-Id: I83fe941b6984be54469bc6b9191f6eacaceaa036 Reviewed-by: Jędrzej Nowacki Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 75 +++++++++++++++------- .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 17 +++++ .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 15 +++++ 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index f969875455..06ada136a6 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -364,33 +364,11 @@ void qMetaTypeLoadHelper(QDataStream &stream, void *t) template <> inline void qMetaTypeLoadHelper(QDataStream &, void *) {} #endif // QT_NO_DATASTREAM -template -struct QMetaTypeId -{ - enum { Defined = 0 }; -}; - -template -struct QMetaTypeId2 -{ - enum { Defined = QMetaTypeId::Defined }; - static inline int qt_metatype_id() { return QMetaTypeId::qt_metatype_id(); } -}; - class QObject; class QWidget; -namespace QtPrivate { - template ::Defined> - struct QMetaTypeIdHelper { - static inline int qt_metatype_id() - { return QMetaTypeId2::qt_metatype_id(); } - }; - template struct QMetaTypeIdHelper { - static inline int qt_metatype_id() - { return -1; } - }; - +namespace QtPrivate +{ template struct IsPointerToTypeDerivedFromQObject { @@ -427,6 +405,38 @@ namespace QtPrivate { Q_STATIC_ASSERT_X(sizeof(T), "Type argument of Q_DECLARE_METATYPE(T*) must be fully defined"); enum { Value = sizeof(checkType(static_cast(0))) == sizeof(yes_type) }; }; +} + +template ::Value> +struct QMetaTypeIdQObject +{ + enum { + Defined = 0 + }; +}; + +template +struct QMetaTypeId : public QMetaTypeIdQObject +{ +}; + +template +struct QMetaTypeId2 +{ + enum { Defined = QMetaTypeId::Defined }; + static inline int qt_metatype_id() { return QMetaTypeId::qt_metatype_id(); } +}; + +namespace QtPrivate { + template ::Defined> + struct QMetaTypeIdHelper { + static inline int qt_metatype_id() + { return QMetaTypeId2::qt_metatype_id(); } + }; + template struct QMetaTypeIdHelper { + static inline int qt_metatype_id() + { return -1; } + }; // Function pointers don't derive from QObject template struct IsPointerToTypeDerivedFromQObject { enum { Value = false }; }; @@ -501,6 +511,23 @@ inline int qRegisterMetaType( #endif } +template +struct QMetaTypeIdQObject +{ + enum { + Defined = 1 + }; + + static int qt_metatype_id() + { + static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); + if (!metatype_id.load()) + metatype_id.storeRelease(qRegisterMetaType(QByteArray(T::staticMetaObject.className() + QByteArrayLiteral("*")).constData(), + reinterpret_cast(quintptr(-1)))); + return metatype_id.loadAcquire(); + } +}; + #ifndef QT_NO_DATASTREAM template inline int qRegisterMetaTypeStreamOperators() diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index f8403f11a1..572ecc9ba8 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -100,12 +100,29 @@ private slots: struct Foo { int i; }; + +class CustomQObject : public QObject +{ + Q_OBJECT +public: + CustomQObject(QObject *parent = 0) + : QObject(parent) + { + } +}; + +class CustomNonQObject {}; + void tst_QMetaType::defined() { QCOMPARE(int(QMetaTypeId2::Defined), 1); QCOMPARE(int(QMetaTypeId2::Defined), 0); QCOMPARE(int(QMetaTypeId2::Defined), 1); QCOMPARE(int(QMetaTypeId2::Defined), 0); + QVERIFY(QMetaTypeId2::Defined); + QVERIFY(!QMetaTypeId2::Defined); + QVERIFY(!QMetaTypeId2::Defined); + QVERIFY(!QMetaTypeId2::Defined); } struct Bar diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index ccdab17668..5aa1389b65 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -2541,8 +2541,23 @@ public: }; Q_DECLARE_METATYPE(CustomQObjectDerived*) +class CustomQObjectDerivedNoMetaType : public CustomQObject { + Q_OBJECT +public: + CustomQObjectDerivedNoMetaType(QObject *parent = 0) : CustomQObject(parent) {} +}; + void tst_QVariant::qvariant_cast_QObject_derived() { + { + CustomQObjectDerivedNoMetaType *object = new CustomQObjectDerivedNoMetaType(this); + QVariant data = QVariant::fromValue(object); + QVERIFY(data.userType() == qMetaTypeId()); + QCOMPARE(data.value(), object); + QCOMPARE(data.value(), object); + QCOMPARE(data.value(), object); + QVERIFY(data.value() == 0); + } { CustomQObjectDerived *object = new CustomQObjectDerived(this); QVariant data = QVariant::fromValue(object); -- cgit v1.2.3 From f5433b9666a4a10779f2244c8c7399c8f794baa4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 6 Mar 2012 01:24:19 +0100 Subject: Merge an overloaded QKeySequence constructor. Change-Id: I14dc9234b9a4822f65338b75482cab05a017dc69 Reviewed-by: Olivier Goffart --- src/gui/kernel/qkeysequence.cpp | 10 ---------- src/gui/kernel/qkeysequence.h | 3 +-- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 153b2b5c2d..b0200335d7 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -934,16 +934,6 @@ QKeySequence::QKeySequence() Note the "File|Open" translator comment. It is by no means necessary, but it provides some context for the human translator. */ -QKeySequence::QKeySequence(const QString &key) -{ - d = new QKeySequencePrivate(); - assign(key); -} - -/*! - \since 4.7 - Creates a key sequence from the \a key string based on \a format. -*/ QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format) { d = new QKeySequencePrivate(); diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index d1e7d06653..e8dd134bc3 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -146,8 +146,7 @@ public: }; QKeySequence(); - QKeySequence(const QString &key); - QKeySequence(const QString &key, SequenceFormat format); + QKeySequence(const QString &key, SequenceFormat format = NativeText); QKeySequence(int k1, int k2 = 0, int k3 = 0, int k4 = 0); QKeySequence(const QKeySequence &ks); QKeySequence(StandardKey key); -- cgit v1.2.3 From 38d566f7131c3f7a1016ab5fe768e6e9a5c8e54e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 2 Mar 2012 15:56:19 +0100 Subject: Cleanup QThread::initialize and QThread::cleanup The qt_global_mutexpool was private API deprecated long time ago. And there is no reason to call qt_create_tls because it is called in QThreadData::current that is called from the QObject constructor, even before QCoreApplication::init can be called. Change-Id: Idf3576d8591377811b727b12edc43dc898570ba4 Reviewed-by: Bradley T. Hughes --- src/corelib/kernel/qcoreapplication.cpp | 5 ----- src/corelib/thread/qmutexpool.cpp | 3 --- src/corelib/thread/qmutexpool_p.h | 2 -- src/corelib/thread/qthread.cpp | 28 ---------------------------- src/corelib/thread/qthread.h | 3 --- 5 files changed, 41 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 184743e865..967ed447d5 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -543,10 +543,6 @@ void QCoreApplication::init() Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = this; -#ifndef QT_NO_THREAD - QThread::initialize(); -#endif - // use the event dispatcher created by the app programmer (if any) if (!QCoreApplicationPrivate::eventDispatcher) QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher; @@ -602,7 +598,6 @@ QCoreApplication::~QCoreApplication() } if (globalThreadPool) globalThreadPool->waitForDone(); - QThread::cleanup(); #endif d_func()->threadData->eventDispatcher = 0; diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp index b102770d23..6b6674ccdf 100644 --- a/src/corelib/thread/qmutexpool.cpp +++ b/src/corelib/thread/qmutexpool.cpp @@ -46,9 +46,6 @@ QT_BEGIN_NAMESPACE -// qt_global_mutexpool is here for backwards compatibility only, -// use QMutexpool::instance() in new clode. -Q_CORE_EXPORT QMutexPool *qt_global_mutexpool = 0; Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive)) /*! diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h index ce55a40bb8..f5428bed52 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/corelib/thread/qmutexpool_p.h @@ -84,8 +84,6 @@ private: QMutex::RecursionMode recursionMode; }; -extern Q_CORE_EXPORT QMutexPool *qt_global_mutexpool; - QT_END_NAMESPACE #endif // QT_NO_THREAD diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 64fd8776ce..ea6760a1b9 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -42,7 +42,6 @@ #include "qthread.h" #include "qthreadstorage.h" #include "qmutex.h" -#include "qmutexpool_p.h" #include "qreadwritelock.h" #include "qabstracteventdispatcher.h" @@ -537,33 +536,6 @@ void QThread::run() (void) exec(); } -/*! \internal - Initializes the QThread system. -*/ -#if defined (Q_OS_WIN) -void qt_create_tls(); -#endif - -void QThread::initialize() -{ - if (qt_global_mutexpool) - return; - qt_global_mutexpool = QMutexPool::instance(); - -#if defined (Q_OS_WIN) - qt_create_tls(); -#endif -} - - -/*! \internal - Cleans up the QThread system. -*/ -void QThread::cleanup() -{ - qt_global_mutexpool = 0; -} - /*! \fn void QThread::setPriority(Priority priority) \since 4.1 diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index ba119afb5d..953632c6fc 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -128,9 +128,6 @@ private: Q_OBJECT Q_DECLARE_PRIVATE(QThread) - static void initialize(); - static void cleanup(); - friend class QCoreApplication; friend class QThreadData; }; -- cgit v1.2.3 From 1e6514a714c1f55b9cb57d2b8b65bc2305c2e2c6 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 2 Mar 2012 16:18:52 +0100 Subject: Don't use QMutexPool from the animation framework Use a plain QBasicMutex instead Change-Id: I1abd35b4fe4e9f0401e73c7c3f503b00bba2baa9 Reviewed-by: Bradley T. Hughes --- src/corelib/animation/qpropertyanimation.cpp | 5 +++-- src/corelib/animation/qvariantanimation.cpp | 22 ++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index fc51a20a15..83ae7bafaa 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -92,7 +92,7 @@ #include "qanimationgroup.h" #include "qpropertyanimation_p.h" -#include +#include #ifndef QT_NO_ANIMATION @@ -268,7 +268,8 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState, QPropertyAnimation *animToStop = 0; { #ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&staticMetaObject)); + static QBasicMutex mutex; + QMutexLocker locker(&mutex); #endif typedef QPair QPropertyAnimationPair; typedef QHash QPropertyAnimationHash; diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 2262a3836e..59b2d6abf3 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #ifndef QT_NO_ANIMATION @@ -399,6 +398,7 @@ void QVariantAnimation::setEasingCurve(const QEasingCurve &easing) typedef QVector QInterpolatorVector; Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators) +static QBasicMutex registeredInterpolatorsMutex; /*! \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress)) @@ -435,9 +435,7 @@ void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator fun // in such an order that we get here with interpolators == NULL, // to continue causes the app to crash on exit with a SEGV if (interpolators) { -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators)); -#endif + QMutexLocker locker(®isteredInterpolatorsMutex); if (int(interpolationType) >= interpolators->count()) interpolators->resize(int(interpolationType) + 1); interpolators->replace(interpolationType, func); @@ -452,14 +450,14 @@ template static inline QVariantAnimation::Interpolator castToInterpo QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType) { - QInterpolatorVector *interpolators = registeredInterpolators(); -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators)); -#endif - QVariantAnimation::Interpolator ret = 0; - if (interpolationType < interpolators->count()) { - ret = interpolators->at(interpolationType); - if (ret) return ret; + { + QInterpolatorVector *interpolators = registeredInterpolators(); + QMutexLocker locker(®isteredInterpolatorsMutex); + QVariantAnimation::Interpolator ret = 0; + if (interpolationType < interpolators->count()) { + ret = interpolators->at(interpolationType); + if (ret) return ret; + } } switch(interpolationType) -- cgit v1.2.3 From 8bf6d6a6caadd4db36bb36d7de7ccb76dd031452 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 2 Mar 2012 15:39:50 +0100 Subject: Don't use QMutexPool in QEventDispatcher Use a QBasicMutex, there is no extra cost of having a mutex for this. Change-Id: Ib5b01338649002c0c21f018b2c931a8cc68027f6 Reviewed-by: Bradley T. Hughes --- src/corelib/kernel/qeventdispatcher_glib.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 4adcb7678c..3f272a2512 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -42,7 +42,6 @@ #include "qeventdispatcher_glib_p.h" #include "qeventdispatcher_unix_p.h" -#include #include #include "qcoreapplication.h" @@ -295,8 +294,8 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) : mainContext(context) { if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) { - static int dummyValue = 0; // only used for its address - QMutexLocker locker(QMutexPool::instance()->get(&dummyValue)); + static QBasicMutex mutex; + QMutexLocker locker(&mutex); if (!g_thread_supported()) g_thread_init(NULL); } -- cgit v1.2.3 From 1fc0e27b17e6d88cd38c72ce38277d810009e0fe Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 24 Feb 2012 19:18:02 +0100 Subject: transitively resolve module dependencies otherwise we need the nasty hack for includes, and CONFIGs and DEFINES from dependencies are not included at all. Change-Id: I7eaee761161a6e8fbac8e9237d26559aa11a88a1 Reviewed-by: Joerg Bornemann Reviewed-by: Marius Storm-Olsen --- mkspecs/features/qt.prf | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 5328e6ccff..21443aa5b5 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -152,21 +152,22 @@ for(QT_CURRENT_VERIFY, $$list($$QT_PLUGIN_VERIFY)) { !isEmpty(QT_BUILD_TREE):QMAKE_LIBDIR = $$QT_BUILD_TREE/lib $$QMAKE_LIBDIR #as above, prepending prevents us from picking up "stale" libs QMAKE_LIBDIR += $$QMAKE_LIBDIR_QT -# Topological ordering of modules based on their QT..depends variable -QT = $$sort_depends(QT, "QT.") - -QT_DEPENDS= - +# Figure out from which modules we're wanting to use the private headers unset(using_privates) +NEWQT = for(QTLIB, QT) { - # Figure out if we're wanting to use the private headers of a module - contains(QTLIB, .*-private) { - QTLIB ~= s/-private// - use_private = UsePrivate - } else { - use_private = NoPrivate + QTLIBRAW = $$replace(QTLIB, -private$, ) + !isEqual(QTLIBRAW, $$QTLIB) { + want_var = QT.$${QTLIBRAW}.want_private + $$want_var = UsePrivate + using_privates = true } - + NEWQT += $$QTLIBRAW +} +# Topological resolution of modules based on their QT..depends variable +QT = $$resolve_depends(NEWQT, "QT.") +# Finally actually add the modules +for(QTLIB, QT) { isEmpty(QT.$${QTLIB}.name) { message("Warning: unknown QT module: $$QTLIB") next() @@ -176,14 +177,9 @@ for(QTLIB, QT) { warning($$TARGET cannot have a QT of $$QTLIB) next() } - qtAddModule($$QTLIB, $$use_private) - QT_DEPENDS += $$eval(QT.$${QTLIB}.depends) - isEqual(use_private, UsePrivate):using_privates = true -} -# add include paths for all .depends, since module/application might need f.ex. template specializations etc. -QT_DEPENDS -= $$QT -for(QTLIB, $$list($$lower($$unique(QT_DEPENDS)))):INCLUDEPATH *= $$INCLUDEPATH $$eval(QT.$${QTLIB}.includes) + qtAddModule($$QTLIB, $$eval(QT.$${QTLIB}.want_private)) +} !isEmpty(using_privates):!no_private_qt_headers_warning:if(!debug_and_release|!build_pass) { message("This project is using private headers and will therefore be tied to this specific Qt module build version.") -- cgit v1.2.3 From 3ff7bc086b9ae3d7288e6a4e1f96974b77105ae0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 6 Mar 2012 10:18:14 +0100 Subject: QProcess/Win: pointless Sleep call removed Change-Id: I634c62d3a0f96bc074e815dfd4106b6187f4ba85 Reviewed-by: Friedemann Kleint Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess_win.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index a52fd46c97..f7c2f965d5 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -530,8 +530,6 @@ void QProcessPrivate::startProcess() notifier->start(NOTIFYTIMEOUT); } - // give the process a chance to start ... - Sleep(SLEEPMIN * 2); _q_startupNotification(); } -- cgit v1.2.3 From 11f9d187312f54dce4f5233b7fe696a0d949facc Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Tue, 6 Mar 2012 13:13:09 +0100 Subject: Fix finding specs in the unsupported/ directory. The -spec argument was interpreted as a relative directory as soon as it contained a slash. Fix this by checking if the directory exists before attempting to interpret it. Change-Id: Ide8f0418abc719b0be582d2d72642a141f6c6dea Reviewed-by: Oswald Buddenhagen --- qmake/option.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qmake/option.cpp b/qmake/option.cpp index 3fc66a8f3d..ef613b90ad 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -149,8 +149,11 @@ static QString detectProjectFile(const QString &path) static QString cleanSpec(const QString &spec) { QString ret = QDir::cleanPath(spec); - if (ret.contains('/')) - ret = QDir::cleanPath(QFileInfo(ret).absoluteFilePath()); + if (ret.contains('/')) { + const QFileInfo specDirInfo(ret); + if (specDirInfo.exists() && specDirInfo.isDir()) + ret = QDir::cleanPath(specDirInfo.absoluteFilePath()); + } return ret; } -- cgit v1.2.3 From 2cf8e487a5c546382daaa954c23d3926668b0a85 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Wed, 22 Feb 2012 21:23:48 +0000 Subject: Windows - fix QWindowsSystemProxy global static race Loser of the race would try to delete an uninitialised pointer Task-number: QTBUG-15765 Change-Id: Ie184ee2306e102aa8fbad752ef09b95c3ede00c2 Reviewed-by: Thiago Macieira --- src/network/kernel/qnetworkproxy_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 6969a9effd..33ae4a6a14 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -256,7 +256,7 @@ public: Q_GLOBAL_STATIC(QWindowsSystemProxy, systemProxy) QWindowsSystemProxy::QWindowsSystemProxy() - : initialized(false), functional(false), isAutoConfig(false) + : hHttpSession(0), initialized(false), functional(false), isAutoConfig(false) { defaultResult << QNetworkProxy::NoProxy; } -- cgit v1.2.3 From 299e7ffd6a8a91f1d4259b91d4a519c1933c5f33 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 5 Mar 2012 14:09:04 +0000 Subject: Fix QNetworkReply ioGetFromHttpWithCache test case Expiration date is calculated from max-age header when a response is inserted into the cache. Because the test case is prepopulating the cache outside of QNAM's control, the expiration date was uninitialised, causing the test to fail. This is due to a 2 year old change in QNAM, where max age calculation was removed from cache retrieval, and more recent changes to QDateTime where secsTo() returns 0 if one of the arguments is invalid. Change-Id: Ieecd46123dde4ca0fd0be3ae79e70e1528ec02bc Reviewed-by: Martin Petersson --- tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index d8f9bf32ad..00b3fd1973 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -3385,6 +3385,7 @@ void tst_QNetworkReply::ioGetFromHttpWithCache_data() << QNetworkCacheMetaData::RawHeader("Cache-control", "max-age=0"); // isn't used in cache loading content.first.setRawHeaders(rawHeaders); content.first.setLastModified(past); + content.first.setExpirationDate(past); QTest::newRow("expired,200,prefer-network") << reply200 << "Reloaded" << content << int(QNetworkRequest::PreferNetwork) << QStringList() << false << true; -- cgit v1.2.3 From c93f7b69486a0d12b475e31eeb699ae07aa928c2 Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Mon, 5 Mar 2012 16:54:12 +0000 Subject: Fix tst_QNetworkReply::httpWithNoCredentialUsage autotest The test was testing the wrong thing, and passing even though QNetworkRequest::AuthenticationReuseAttribute was not being respected, until recently when I fixed username/password in URLs Now the cache is properly bypassed when this attribute is set to manual, and the autotest is updated to check this. Change-Id: I87943515562d0b16b03504f0758ba265758d1c22 Reviewed-by: Martin Petersson --- src/network/access/qnetworkaccessmanager.cpp | 10 ++-- src/network/access/qnetworkaccessmanager_p.h | 3 +- src/network/access/qnetworkreplyhttpimpl.cpp | 4 +- .../access/qnetworkreply/tst_qnetworkreply.cpp | 55 +++++++++++++++------- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 60c28274c6..c65edb6673 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1089,15 +1089,16 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen QNetworkReply *reply, bool synchronous, QUrl &url, - QUrl *urlForLastAuthentication) + QUrl *urlForLastAuthentication, + bool allowAuthenticationReuse) { Q_Q(QNetworkAccessManager); // don't try the cache for the same URL twice in a row // being called twice for the same URL means the authentication failed // also called when last URL is empty, e.g. on first call - if (urlForLastAuthentication->isEmpty() - || url != *urlForLastAuthentication) { + if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty() + || url != *urlForLastAuthentication)) { // if credentials are included in the url, then use them if (!url.userName().isEmpty() && !url.password().isEmpty()) { @@ -1124,7 +1125,8 @@ void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authen *urlForLastAuthentication = url; emit q->authenticationRequired(reply, authenticator); - authenticationManager->cacheCredentials(url, authenticator); + if (allowAuthenticationReuse) + authenticationManager->cacheCredentials(url, authenticator); } #ifndef QT_NO_NETWORKPROXY diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 0733756be4..b0bcaabacc 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -98,7 +98,8 @@ public: QNetworkReply *reply, bool synchronous, QUrl &url, - QUrl *urlForLastAuthentication); + QUrl *urlForLastAuthentication, + bool allowAuthenticationReuse = true); void cacheCredentials(const QUrl &url, const QAuthenticator *auth); QNetworkAuthenticationCredential *fetchCachedCredentials(const QUrl &url, const QAuthenticator *auth = 0); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 2124395de3..1f456746ae 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1179,10 +1179,10 @@ void QNetworkReplyHttpImplPrivate::replyDownloadProgressSlot(qint64 bytesReceive emit q->downloadProgress(bytesDownloaded, bytesTotal); } -void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetworkRequest &, +void QNetworkReplyHttpImplPrivate::httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth) { - managerPrivate->authenticationRequired(auth, q_func(), synchronous, url, &urlForLastAuthentication); + managerPrivate->authenticationRequired(auth, q_func(), synchronous, url, &urlForLastAuthentication, request.withCredentials()); } #ifndef QT_NO_NETWORKPROXY diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 00b3fd1973..8685546a5f 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -6335,29 +6335,52 @@ void tst_QNetworkReply::qtbug13431replyThrottling() void tst_QNetworkReply::httpWithNoCredentialUsage() { - QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi")); - // Do not use credentials - request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual); QNetworkAccessManager manager; - QNetworkReplyPtr reply = manager.get(request); - qRegisterMetaType("QNetworkReply*"); - qRegisterMetaType("QAuthenticator*"); QSignalSpy authSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); QSignalSpy finishedSpy(&manager, SIGNAL(finished(QNetworkReply*))); - qRegisterMetaType("QNetworkReply::NetworkError"); - QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError))); - connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); - QTestEventLoop::instance().enterLoop(10); - QVERIFY(!QTestEventLoop::instance().timeout()); + // Get with credentials, to preload authentication cache + { + QNetworkRequest request(QUrl("http://httptest:httptest@" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi")); + QNetworkReplyPtr reply = manager.get(request); + QVERIFY(waitForFinish(reply) == Success); + // credentials in URL, so don't expect authentication signal + QCOMPARE(authSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 1); + finishedSpy.clear(); + } - // We check if authenticationRequired was emitted, however we do not anything in it so it should be 401 - QCOMPARE(authSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 1); - QCOMPARE(errorSpy.count(), 1); + // Get with cached credentials (normal usage) + { + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi")); + QNetworkReplyPtr reply = manager.get(request); + QVERIFY(waitForFinish(reply) == Success); + // credentials in cache, so don't expect authentication signal + QCOMPARE(authSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 1); + finishedSpy.clear(); + } - QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + // Do not use cached credentials (webkit cross origin usage) + { + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/protected/cgi-bin/md5sum.cgi")); + request.setAttribute(QNetworkRequest::AuthenticationReuseAttribute, QNetworkRequest::Manual); + QNetworkReplyPtr reply = manager.get(request); + + QSignalSpy errorSpy(reply, SIGNAL(error(QNetworkReply::NetworkError))); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + // We check if authenticationRequired was emitted, however we do not anything in it so it should be 401 + QCOMPARE(authSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 1); + QCOMPARE(errorSpy.count(), 1); + + QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + } } void tst_QNetworkReply::qtbug15311doubleContentLength() -- cgit v1.2.3 From 47cdc50bbcdab874e5cbd11ae3a91eb2b5abab54 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 1 Mar 2012 08:47:20 +0100 Subject: QTouchEvent::TouchPoint: make it a proper value class This includes: - Marking it as Q_MOVABLE_TYPE - adding move ctor and move assignment operator - add member-swap - use the copy-swap idiom in the copy-assignment operator This required making the destructor safe for d == nullptr. Change-Id: I8a77ffcb8e4a395a7e103d1df610561b6ae4c001 Reviewed-by: Stephen Kelly Reviewed-by: Thiago Macieira --- src/gui/kernel/qevent.cpp | 19 +++++++++---------- src/gui/kernel/qevent.h | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 60e754b289..f1bf07635c 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3621,7 +3621,7 @@ QTouchEvent::TouchPoint::TouchPoint(const QTouchEvent::TouchPoint &other) */ QTouchEvent::TouchPoint::~TouchPoint() { - if (!d->ref.deref()) + if (d && !d->ref.deref()) delete d; } @@ -4043,16 +4043,15 @@ void QTouchEvent::TouchPoint::setFlags(InfoFlags flags) d->flags = flags; } -/*! \internal */ -QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other) -{ - other.d->ref.ref(); - if (!d->ref.deref()) - delete d; - d = other.d; - return *this; -} +/*! + \fn QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::TouchPoint &other) + \internal + */ +/*! + \fn void QTouchEvent::TouchPoint::swap(TouchPoint &other); + \internal +*/ /*! \class QScrollPrepareEvent diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index d70f6be201..7c871b0dda 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -713,9 +713,19 @@ public: Q_DECLARE_FLAGS(InfoFlags, InfoFlag) explicit TouchPoint(int id = -1); - TouchPoint(const QTouchEvent::TouchPoint &other); + TouchPoint(const TouchPoint &other); +#ifdef Q_COMPILER_RVALUE_REFS + TouchPoint(TouchPoint &&other) : d(other.d) { other.d = 0; } + TouchPoint &operator=(TouchPoint &&other) + { qSwap(d, other.d); return *this; } +#endif ~TouchPoint(); + TouchPoint &operator=(const TouchPoint &other) + { if ( d != other.d ) { TouchPoint copy(other); swap(copy); } return *this; } + + void swap(TouchPoint &other) { qSwap(d, other.d); } + int id() const; Qt::TouchPointState state() const; @@ -767,7 +777,6 @@ public: void setVelocity(const QVector2D &v); void setFlags(InfoFlags flags); void setRawScreenPositions(const QList &positions); - QTouchEvent::TouchPoint &operator=(const QTouchEvent::TouchPoint &other); private: QTouchEventTouchPointPrivate *d; @@ -819,7 +828,7 @@ protected: friend class QApplication; friend class QApplicationPrivate; }; - +Q_DECLARE_TYPEINFO(QTouchEvent::TouchPoint, Q_MOVABLE_TYPE); Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchEvent::TouchPoint::InfoFlags) class QScrollPrepareEventPrivate; -- cgit v1.2.3 From 676304e706266f09357ad8bfbe6c4c281f3f3873 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 2 Mar 2012 15:46:39 +0100 Subject: Add test for QUrl::isLocalFile (there weren't any). Change-Id: I839d2eee7b0651700516d6140635151a52a9fa40 Reviewed-by: Thiago Macieira --- tests/auto/corelib/io/qurl/tst_qurl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index a74d817b8a..f782b26b46 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -1001,6 +1001,7 @@ void tst_QUrl::toLocalFile() QUrl url(theUrl); QCOMPARE(url.toLocalFile(), theFile); + QCOMPARE(url.isLocalFile(), !theFile.isEmpty()); } void tst_QUrl::fromLocalFile_data() -- cgit v1.2.3 From 092a270afde4fade3dbe36fde7156e5a462a13cb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 5 Mar 2012 21:03:09 +0100 Subject: fix relative default examples path copy&pasto ... Change-Id: I73ab90f31f2a2250abe1ec9aeea975122ff319cb Reviewed-by: Joerg Bornemann Reviewed-by: Mark Brand --- src/corelib/global/qlibraryinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 4caacece2d..cb4e0e753f 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -226,7 +226,7 @@ static const struct { { "Imports", "imports" }, { "Data", "" }, { "Translations", "translations" }, - { "Examples", "" }, + { "Examples", "examples" }, { "Tests", "tests" }, #ifdef QT_BUILD_QMAKE { "Sysroot", "" }, -- cgit v1.2.3 From 4958c138a79f6597b635aa0ed356f0fbd8fa929c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 2 Mar 2012 17:27:33 +0100 Subject: don't add bogus /mkspecs to QMAKE_MKSPECS the project build root can of course be empty - if there is neither an mkspecs/ nor a .qmake.cache - or no project in the first place (-query). Change-Id: I9595b0b4ad80a9086dcd48c9ae62b3e8bd1b6f2f Reviewed-by: Joerg Bornemann --- qmake/option.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qmake/option.cpp b/qmake/option.cpp index ef613b90ad..b2a1e6982f 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -594,7 +594,8 @@ QStringList Option::mkspecPaths() for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) ret << ((*it) + concat); } - ret << Option::mkfile::project_build_root + concat; + if (!Option::mkfile::project_build_root.isEmpty()) + ret << Option::mkfile::project_build_root + concat; if (!Option::mkfile::project_root.isEmpty()) ret << Option::mkfile::project_root + concat; ret << QLibraryInfo::location(QLibraryInfo::HostDataPath) + concat; -- cgit v1.2.3 From c7cb455a47c42e8e658e3433defee613f8643cd2 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 23 Jan 2012 22:47:59 +0000 Subject: QRegularExpression: add QRegularExpression* set of classes Added QRegularExpression, QRegularExpressionMatch and QRegularExpressionMatchIterator as PCRE-enabled, regexp classes. Documentation is included, as well as a first round of autotests. Task-number: QTBUG-23489 Change-Id: Id47031b80602c913ccd2fd740070e3024ea06abc Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- dist/changes-5.0.0 | 5 + .../files-and-resources/datastreamformat.qdoc | 5 + .../code/src_corelib_tools_qregularexpression.cpp | 289 +++ src/corelib/tools/qregularexpression.cpp | 2022 ++++++++++++++++++++ src/corelib/tools/qregularexpression.h | 245 +++ src/corelib/tools/tools.pri | 8 + .../corelib/tools/qregularexpression/.gitignore | 1 + .../qregularexpression/qregularexpression.pro | 4 + .../qregularexpression/tst_qregularexpression.cpp | 1150 +++++++++++ tests/auto/corelib/tools/tools.pro | 1 + 10 files changed, 3730 insertions(+) create mode 100644 doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp create mode 100644 src/corelib/tools/qregularexpression.cpp create mode 100644 src/corelib/tools/qregularexpression.h create mode 100644 tests/auto/corelib/tools/qregularexpression/.gitignore create mode 100644 tests/auto/corelib/tools/qregularexpression/qregularexpression.pro create mode 100644 tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 93f8543fd8..dd0a0693ed 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -317,6 +317,11 @@ QtCore * QIntValidator and QDoubleValidator no longer fall back to using the C locale if the requested locale fails to validate the input. +* A new set of classes for doing pattern matching with Perl-compatible regular + expressions has been added: QRegularExpression, QRegularExpressionMatch and + QRegularExpressionMatchIterator. They aim to replace QRegExp with a more + powerful and flexible regular expression engine. + QtGui ----- * Accessibility has been refactored. The hierachy of accessible objects is implemented via diff --git a/doc/src/network/files-and-resources/datastreamformat.qdoc b/doc/src/network/files-and-resources/datastreamformat.qdoc index 17a0044a69..8ff31371a2 100644 --- a/doc/src/network/files-and-resources/datastreamformat.qdoc +++ b/doc/src/network/files-and-resources/datastreamformat.qdoc @@ -298,6 +298,11 @@ \li Regular expression syntax (quint8) \li Minimal matching (quint8) \endlist + \row \li QRegularExpression + \li \list + \li The regular expression pattern (QString) + \li The pattern options (quint32) + \endlist \row \li QRegion \li \list \li The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32) diff --git a/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp b/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp new file mode 100644 index 0000000000..cab89d9c9e --- /dev/null +++ b/doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +QRegularExpression re("a pattern"); +//! [0] + + +//! [1] +QRegularExpression re; +re.setPattern("another pattern"); +//! [1] + + +//! [2] +// matches two digits followed by a space and a word +QRegularExpression re("\\d\\d \\w+"); + +// matches a backslash +QRegularExpression re2("\\\\"); +//! [2] + + +//! [3] +QRegularExpression re("a third pattern"); +QString pattern = re.pattern(); // pattern == "a third pattern" +//! [3] + + +//! [4] +// matches "Qt rocks", but also "QT rocks", "QT ROCKS", "qT rOcKs", etc. +QRegularExpression re("Qt rocks", QRegularExpression::CaseInsensitiveOption); +//! [4] + + +//! [5] +QRegularExpression re("^\\d+$"); +re.setPatternOptions(QRegularExpression::MultilineOption); +// re matches any line in the subject string that contains only digits (but at least one) +//! [5] + + +//! [6] +QRegularExpression re = QRegularExpression("^two.*words$", QRegularExpression::MultilineOption + | QRegularExpression::DotMatchesEverythingOption); + +QRegularExpression::PatternOptions options = re.patternOptions(); +// options == QRegularExpression::MultilineOption | QRegularExpression::DotMatchesEverythingOption +//! [6] + + +//! [7] +// match two digits followed by a space and a word +QRegularExpression re("\\d\\d \\w+"); +QRegularExpressionMatch match = re.match("abc123 def"); +bool hasMatch = match.hasMatch(); // true +//! [7] + + +//! [8] +QRegularExpression re("\\d\\d \\w+"); +QRegularExpressionMatch match = re.match("abc123 def"); +if (match.hasMatch()) { + QString matched = match.captured(0); // matched == "23 def" + // ... +} +//! [8] + + +//! [9] +QRegularExpression re("\\d\\d \\w+"); +QRegularExpressionMatch match = re.match("12 abc 45 def", 1); +if (match.hasMatch()) { + QString matched = match.captured(0); // matched == "45 def" + // ... +} +//! [9] + + +//! [10] +QRegularExpression re("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$"); +QRegularExpressionMatch match = re.match("08/12/1985"); +if (match.hasMatch()) { + QString day = re.captured(1); // day == "08" + QString month = re.captured(2); // month == "12" + QString year = re.captured(3); // year == "1985" + // ... +} +//! [10] + + +//! [11] +QRegularExpression re("abc(\\d+)def"); +QRegularExpressionMatch match = re.match("XYZabc123defXYZ"); +if (match.hasMatch()) { + int startOffset = re.capturedStart(1); // startOffset == 6 + int endOffset = re.capturedEnd(1); // endOffset == 9 + // ... +} +//! [11] + + +//! [12] +QRegularExpression re("^(?\\d\\d)/(?\\d\\d)/(?\\d\\d\\d\\d)$"); +QRegularExpressionMatch match = re.match("08/12/1985"); +if (match.hasMatch()) { + QString date = match.captured("date"); // date == "08" + QString month = match.captured("month"); // month == "12" + QString year = match.captured("year"); // year == 1985 +} +//! [12] + + +//! [13] +QRegularExpression re("(\\w+)"); +QRegularExpressionMatchIterator i = re.globalMatch("the quick fox"); +//! [13] + + +//! [14] +QStringList words; +while (i.hasNext()) { + QRegularExpressionMatch match = i.next(); + QString word = match.captured(1); + words << word; +} +// words contains "the", "quick", "fox" +//! [14] + + +//! [15] +QString pattern("^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \\d\\d?, \\d\\d\\d\\d$"); +QRegularExpression re(pattern); + +QString input("Jan 21,"); +QRegularExpressionMatch match = re.match(input, 0, QRegularExpressionMatch::PartialPreferCompleteMatch); +bool hasMatch = match.hasMatch(); // false +bool hasPartialMatch = match.hasPartialMatch(); // true +//! [15] + + +//! [16] +QString input("Dec 8, 1985"); +QRegularExpressionMatch match = re.match(input, 0, QRegularExpressionMatch::PartialPreferCompleteMatch); +bool hasMatch = match.hasMatch(); // true +bool hasPartialMatch = match.hasPartialMatch(); // false +//! [16] + + +//! [17] +QRegularExpression re("abc\\w+X|def"); +QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpressionMatch::PartialPreferCompleteMatch); +bool hasMatch = match.hasMatch(); // true +bool hasPartialMatch = match.hasPartialMatch(); // false +QString captured = match.captured(0); // captured == "def" +//! [17] + + +//! [18] +QRegularExpression re("abc\\w+X|defY"); +QRegularExpressionMatch match = re.match("abcdef", 0, QRegularExpressionMatch::PartialPreferCompleteMatch); +bool hasMatch = match.hasMatch(); // false +bool hasPartialMatch = match.hasPartialMatch(); // true +QString captured = match.captured(0); // captured == "abcdef" +//! [18] + + +//! [19] +QRegularExpression re("abc|ab"); +QRegularExpressionMatch match = re.match("ab", 0, QRegularExpressionMatch::PartialPreferFirstMatch); +bool hasMatch = match.hasMatch(); // false +bool hasPartialMatch = match.hasPartialMatch(); // true +//! [19] + + +//! [20] +QRegularExpression re("abc(def)?"); +QRegularExpressionMatch match = re.match("abc", 0, QRegularExpressionMatch::PartialPreferFirstMatch); +bool hasMatch = match.hasMatch(); // false +bool hasPartialMatch = match.hasPartialMatch(); // true +//! [20] + +//! [21] +QRegularExpression re("(abc)*"); +QRegularExpressionMatch match = re.match("abc", 0, QRegularExpressionMatch::PartialPreferFirstMatch); +bool hasMatch = match.hasMatch(); // false +bool hasPartialMatch = match.hasPartialMatch(); // true +//! [21] + +//! [22] +QRegularExpression invalidRe("(unmatched|parenthesis"); +bool isValid = invalidRe.isValid(); // false +//! [22] + +//! [23] +QRegularExpression invalidRe("(unmatched|parenthesis"); +if (!invalidRe.isValid()) { + QString errorString = invalidRe.errorString(); // errorString == "missing )" + int errorOffset = invalidRe.patternErrorOffset(); // errorOffset == 22 + // ... +} +//! [23] + +//! [24] +QRegularExpression re("^this pattern must match exactly$"); +//! [24] + +//! [25] +QString p("a .*|pattern"); +QRegularExpression re("\\A(?:" + p + ")\\z"); // re matches exactly the pattern string p +//! [25] + +//! [26] +QString escaped = QRegularExpression::escape("a(x) = f(x) + g(x)"); +// escaped == "a\\(x\\)\\ \\=\\ f\\(x\\)\\ \\+\\ g\\(x\\)" +//! [26] + +//! [27] +QString pattern = "(" + QRegularExpression::escape(name) + + "|" + QRegularExpression::escape(nickname) + ")"; +QRegularExpression re(pattern); +//! [27] + +//! [28] +QRegularExpressionMatch match = re.match(...); +for (int i = 0; i <= match.lastCapturedIndex(); ++i) { + QString captured = match.captured(i); + // ... +} +//! [28] + +//! [29] +QRegularExpression("(\d\d) (?\w+)"); +QRegularExpressionMatch match = re.match("23 Jordan"); +if (match.hasMatch()) { + QString number = match.captured(1); // first == "23" + QString name = match.captured("name"); // name == "Jordan" +} +//! [29] + +//! [30] +// extracts the words +QRegularExpression re("(\w+)"); +QString subject("the quick fox"); +QRegularExpressionMatchIterator i = re.globalMatch(subject); +while (i.hasNext()) { + QRegularExpressionMatch match = i.next(); + // ... +} +//! [30] + + diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp new file mode 100644 index 0000000000..488a454aaa --- /dev/null +++ b/src/corelib/tools/qregularexpression.cpp @@ -0,0 +1,2022 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qregularexpression.h" + +#include +#include +#include +#include +#include + +#include + +// after how many usages we optimize the regexp +static const unsigned int OPTIMIZE_AFTER_USE_COUNT = 10; + +QT_BEGIN_NAMESPACE + +/*! + \class QRegularExpression + \reentrant + + \brief The QRegularExpression class provides pattern matching using regular + expressions. + + \since 5.0 + + \ingroup tools + \ingroup shared + + \keyword regular expression + + Regular expressions, or \e{regexps}, are a very powerful tool to handle + strings and texts. This is useful in many contexts, e.g., + + \table + \row \i Validation + \i A regexp can test whether a substring meets some criteria, + e.g. is an integer or contains no whitespace. + \row \i Searching + \i A regexp provides more powerful pattern matching than + simple substring matching, e.g., match one of the words + \e{mail}, \e{letter} or \e{correspondence}, but none of the + words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc. + \row \i Search and Replace + \i A regexp can replace all occurrences of a substring with a + different substring, e.g., replace all occurrences of \e{&} + with \e{\&} except where the \e{&} is already followed by + an \e{amp;}. + \row \i String Splitting + \i A regexp can be used to identify where a string should be + split apart, e.g. splitting tab-delimited strings. + \endtable + + This document is by no means a complete reference to pattern matching using + regular expressions, and the following parts will require the reader to + have some basic knowledge about Perl-like regular expressions and their + pattern syntax. + + Good references about regular expressions include: + + \list + \o \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. + Friedl, ISBN 0-596-52812-4; + \o the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing + the pattern syntax supported by PCRE (the reference implementation of + Perl-compatible regular expressions); + \o the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression + documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's + regular expression tutorial}. + \endlist + + \tableofcontents + + \section1 Introduction + + QRegularExpression implements Perl-compatible regular expressions. It fully + supports Unicode. For an overview of the regular expression syntax + supported by QRegularExpression, please refer to the aforementioned + pcrepattern(3) man page. A regular expression is made up of two things: a + \bold{pattern string} and a set of \bold{pattern options} that change the + meaning of the pattern string. + + You can set the pattern string by passing a string to the QRegularExpression + constructor: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 0 + + This sets the pattern string to \c{a pattern}. You can also use the + setPattern() function to set a pattern on an existing QRegularExpression + object: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 1 + + Note that due to C++ literal strings rules, you must escape all backslashes + inside the pattern string with another backslash: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 2 + + The pattern() function returns the pattern that it's currently set for a + QRegularExpression object: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 3 + + \section1 Pattern options + + The meaning of the pattern string can be modified by setting one or more + \e{pattern options}. For instance, it is possible to set a pattern to match + case insensitively by setting the QRegularExpression::CaseInsensitiveOption. + + You can set the options by passing them to the QRegularExpression + constructor, as in: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 4 + + Alternatively, you can use the setPatternOptions() function on an existing + QRegularExpressionObject: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 5 + + It is possible to get the pattern options currently set on a + QRegularExpression object by using the patternOptions() function: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 6 + + Please refer to the QRegularExpression::PatternOption enum documentation for + more information about each pattern option. + + \section1 Match type and match options + + The last two arguments of the match() and the globalMatch() functions set + the match type and the match options. The match type is a value of the + QRegularExpression::MatchType enum; the "traditional" matching algorithm is + chosen by using the NormalMatch match type (the default). It is also + possible to enable partial matching of the regular expression against a + subject string: see the \l{partial matching} section for more details. + + The match options are a set of one or more QRegularExpression::MatchOption + values. They change the way a specific match of a regular expression + against a subject string is done. Please refer to the + QRegularExpression::MatchOption enum documentation for more details. + + \target normal matching + \section1 Normal matching + + In order to perform a match you can simply invoke the match() function + passing a string to match against. We refer to this string as the + \e{subject string}. The result of the match() function is a + QRegularExpressionMatch object that can be used to inspect the results of + the match. For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 7 + + If a match is successful, the (implicit) capturing group number 0 can be + used to retrieve the substring matched by the entire pattern (see also the + section about \l{extracting captured substrings}): + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 8 + + It's also possible to start a match at an arbitrary offset inside the + subject string by passing the offset as an argument of the + match() function. In the following example \c{"12 abc"} + is not matched because the match is started at offset 1: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 9 + + \target extracting captured substrings + \section2 Extracting captured substrings + + The QRegularExpressionMatch object contains also information about the + substrings captured by the capturing groups in the pattern string. The + \l{QRegularExpressionMatch::}{captured()} function will return the string + captured by the n-th capturing group: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 10 + + Capturing groups in the pattern are numbered starting from 1, and the + implicit capturing group 0 is used to capture the substring that matched + the entire pattern. + + It's also possible to retrieve the starting and the ending offsets (inside + the subject string) of each captured substring, by using the + \l{QRegularExpressionMatch::}{capturedStart()} and the + \l{QRegularExpressionMatch::}{capturedEnd()} functions: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 11 + + All of these functions have an overload taking a QString as a parameter + in order to extract \e{named} captured substrings. For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 12 + + \target global matching + \section1 Global matching + + \e{Global matching} is useful to find all the occurrences of a given + regular expression inside a subject string. Suppose that we want to extract + all the words from a given string, where a word is a substring matching + the pattern \c{\w+}. + + QRegularExpression::globalMatch returns a QRegularExpressionMatchIterator, + which is a Java-like forward iterator that can be used to iterate over the + results. For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 13 + + Since it's a Java-like iterator, the QRegularExpressionMatchIterator will + point immediately before the first result. Every result is returned as a + QRegularExpressionMatch object. The + \l{QRegularExpressionMatchIterator::}{hasNext()} function will return true + if there's at least one more result, and + \l{QRegularExpressionMatchIterator::}{next()} will return the next result + and advance the iterator. Continuing from the previous example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 14 + + You can also use \l{QRegularExpressionMatchIterator::}{peekNext()} to get + the next result without advancing the iterator. + + It is possible to pass a starting offset and one or more match options to + the globalMatch() function, exactly like normal matching with match(). + + \target partial matching + \section1 Partial matching + + A \e{partial match} is obtained when the end of the subject string is + reached, but more characters are needed to successfully complete the match. + Note that a partial match is usually much more inefficient than a normal + match because many optimizations of the matching algorithm cannot be + employed. + + A partial match must be explicitly requested by specifying a match type of + PartialPreferCompleteMatch or PartialPreferFirstMatch when calling + QRegularExpression::match or QRegularExpression::globalMatch. If a partial + match is found, then calling the \l{QRegularExpressionMatch::}{hasMatch()} + function on the QRegularExpressionMatch object returned by match() will + return \c{false}, but \l{QRegularExpressionMatch::}{hasPartialMatch()} will return + \c{true}. + + When a partial match is found, no captured substrings are returned, and the + (implicit) capturing group 0 corresponding to the whole match captures the + partially matched substring of the subject string. + + Note that asking for a partial match can still lead to a complete match, if + one is found; in this case, \l{QRegularExpressionMatch::}{hasMatch()} will + return \c{true} and \l{QRegularExpressionMatch::}{hasPartialMatch()} + \c{false}. It never happens that a QRegularExpressionMatch reports both a + partial and a complete match. + + Partial matching is mainly useful in two scenarios: validating user input + in real time and incremental/multi-segment matching. + + \target + \section2 Validating user input + + Suppose that we would like the user to input a date in a specific + format, for instance "MMM dd, yyyy". We can check the input validity with + a pattern like: + + \c{^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?, \d\d\d\d$} + + (This pattern doesn't catch invalid days, but let's keep it for the + example's purposes). + + We would like to validate the input with this regular expression \e{while} + the user is typing it, so that we can report an error in the input as soon + as it is committed (for instance, the user typed the wrong key). In order + to do so we must distinguish three cases: + + \list + \o the input cannot possibly match the regular expression; + \o the input does match the regular expression; + \o the input does not match the regular expression right now, + but it will if more charaters will be added to it. + \endlist + + Note that these three cases represent exactly the possible states of a + QValidator (see the QValidator::State enum). + + In particular, in the last case we want the regular expression engine to + report a partial match: we are successfully matching the pattern against + the subject string but the matching cannot continue because the end of the + subject is encountered. Notice, however, that the matching algorithm should + continue and try all possibilities, and in case a complete (non-partial) + match is found, then this one should be reported, and the input string + accepted as fully valid. + + This behaviour is implemented by the PartialPreferCompleteMatch match type. + For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 15 + + If matching the same regular expression against the subject string leads to + a complete match, it is reported as usual: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 16 + + Another example with a different pattern, showing the behaviour of + preferring a complete match over a partial one: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 17 + + In this case, the subpattern \c{abc\\w+X} partially matches the subject + string; however, the subpattern \c{def} matches the subject string + completely, and therefore a complete match is reported. + + In case multiple partial matches are found when matching (but no complete + match), then the QRegularExpressionMatch will report the first one that it + is found. For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 18 + + \section2 Incremental/multi-segment matching + + Incremental matching is another use case of partial matching. Suppose that + we want to find the occurrences of a regular expression inside a large text + (that is, substrings matching the regular expression). In order to do so we + would like to "feed" the large text to the regular expression engines in + smaller chunks. The obvious problem is what happens if the substring that + matches the regular expression spans across two or more chunks. + + In this case, the regular expression engine should report a partial match, + so that we can match again adding new data and (eventually) get a complete + match. This implies that the regular expression engine may assume that + there are other characters \e{beyond the end} of the subject string. This + is not to be taken literally -- the engine will never try to access + any character after the last one in the subject. + + QRegularExpression implements this behaviour when using the + PartialPreferFirstMatch match type. This match type reports a partial match + as soon as it is found, and other match alternatives are not tried + (even if they could lead to a complete match). For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 19 + + This happens because when matching the first branch of the alternation + operator a partial match is found, and therefore matching stops, without + trying the second branch. Another example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 20 + + This shows what could seem a counterintuitve behaviour of quantifiers: + since \c{?} is greedy, then the engine tries first to continue the match + after having matched \c{"abc"}; but then the matching reaches the end of the + subject string, and therefore a partial match is reported. This is + even more surprising in the following example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 21 + + It's easy to understand this behaviour if we remember that the engine + expects the subject string to be only a substring of the whole text we're + looking for a match into (that is, how we said before, that the engine + assumes that there are other characters beyond the end of the subject + string). + + Since the \c{*} quantifier is greedy, then reporting a complete match could + be an error, because after the current subject \c{"abc"} there may be other + occurrences of \c{"abc"}. For instance, the complete text could have been + "abcabcX", and therefore the \e{right} match to report (in the complete + text) would have been \c{"abcabc"}; by matching only against the leading + \c{"abc"} we instead get a partial match. + + \section1 Error handling + + It is possible for a QRegularExpression object to be invalid because of + syntax errors in the pattern string. The isValid() function will return + true if the regular expression is valid, or false otherwise: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 22 + + You can get more information about the specific error by calling the + errorString() function; moreover, the patternErrorOffset() function + will return the offset inside the pattern string + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 23 + + If a match is attempted with an invalid QRegularExpression, then the + returned QRegularExpressionMatch object will be invalid as well (that is, + its \l{QRegularExpressionMatch::}{isValid()} function will return false). + The same applies for attempting a global match. + + \section1 Unsupported Perl-compatible regular expressions features + + QRegularExpression does not support all the features available in + Perl-compatible regular expressions. The most notable one is the fact that + duplicated names for capturing groups are not supported, and using them can + lead to undefined behaviour. + + This may change in a future version of Qt. + + \section1 Notes for QRegExp users + + The QRegularExpression class introduced in Qt 5 is a big improvement upon + QRegExp, in terms of APIs offered, supported pattern syntax and speed of + execution. The biggest difference is that QRegularExpression simply holds a + regular expression, and it's \e{not} modified when a match is requested. + Instead, a QRegularExpressionMatch object is returned, in order to check + the result of a match and extract the captured substring. The same applies + with global matching and QRegularExpressionMatchIterator. + + Other differences are outlined below. + + \section2 Exact matching + + QRegExp::exactMatch in Qt 4 served for two purposes: it exactly matched + a regular expression against a subject string, and it implemented partial + matching. In fact, if an exact match was not found, one could still find + out how much of the subject string was matched by the regular expression + by calling QRegExp::matchedLength(). If the returned length was equal + to the subject string's length, then one could desume that a partial match + was found. + + QRegularExpression supports partial matching explicitly by means of the + appropriate MatchType. If instead you simply want to be sure that the + subject string matches the regular expression exactly, you can wrap the + pattern between a couple of anchoring expressions. Simply + putting the pattern between the \c{^} and the \c{$} anchors is enough + in most cases: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 24 + + However, remember that the \c{$} anchor not only matches at the end of the + string, but also at a newline character right before the end of the string; + that is, the previous pattern matches against the string "this pattern must + match exactly\n". Also, the behaviour of both the \c{^} and the \c{$} + anchors changes if the MultiLineOption is set either explicitely (as a + pattern option) or implicitly (as a directive inside the pattern string). + + Therefore, in the most general case, you should wrap the pattern between + the \c{\A} and the \c{\z} anchors: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 25 + + Note the usage of the non-capturing group in order to preserve the meaning + of the branch operator inside the pattern. + + \section2 Global matching + + Due to limitations of the QRegExp API it was impossible to implement global + matching correctly (that is, like Perl does). In particular, patterns that + can match 0 characters (like \c{"a*"}) are problematic. + + QRegularExpression::globalMatch implements Perl global match correctly, and + the returned iterator can be used to examine each result. + + \section2 Wildcard matching + + There is no equivalent of wildcard matching in QRegularExpression. + Nevertheless, rewriting a regular expression in wildcard syntax to a + Perl-compatible regular expression is a very easy task, given the fact + that wildcard syntax supported by QRegExp is very simple. + + \section2 Other pattern syntaxes + + QRegularExpression supports only Perl-compatible regular expressions. + + \section2 Minimal matching + + QRegExp::setMinimal implemented minimal matching by simply reversing the + greediness of the quantifiers (QRegExp did not support lazy quantifiers, + like \c{*?}, \c{+?}, etc.). QRegularExpression instead does support greedy, + lazy and possessive quantifiers. The InvertedGreedinessOption + pattern option can be useful to emulate the effects of QRegExp::setMinimal: + if enabled, it inverts the greediness of quantifiers (greedy ones become + lazy and vice versa). + + \section2 Caret modes + + The AnchoredMatchOption match option can be used to emulate the + QRegExp::CaretAtOffset behaviour. There is no equivalent for the other + QRegExp::CaretMode modes. + + \sa QRegularExpressionMatch, QRegularExpressionMatchIterator +*/ + +/*! + \class QRegularExpressionMatch + \reentrant + + \brief The QRegularExpressionMatch class provides the results of a matching + a QRegularExpression against a string. + + \since 5.0 + + \ingroup tools + \ingroup shared + + \keyword regular expression match + + A QRegularExpressionMatch object can be obtained by calling the + QRegularExpression::match() function, or as a single result of a global + match from a QRegularExpressionMatchIterator. + + The success or the failure of a match attempt can be inspected by calling + the hasMatch() function. QRegularExpressionMatch also reports a successful + partial match through the hasPartialMatch() function. + + In addition, QRegularExpressionMatch returns the substrings captured by the + capturing groups in the pattern string. The implicit capturing group with + index 0 captures the result of the whole match. The captured() function + returns each substring captured, either by the capturing group's index or + by its name: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 29 + + For each captured substring it is possible to query its starting and ending + offsets in the subject string by calling the capturedStart() and the + capturedEnd() function, respectively. The length of each captured + substring is available using the capturedLength() function. + + The convenience function capturedTexts() will return \e{all} the captured + substrings at once (including the substring matched by the entire pattern) + in the order they have been captured by captring groups; that is, + \c{captured(i) == capturedTexts().at(i)}. + + You can retrieve the QRegularExpression object the subject string was + matched against by calling the regularExpression() function; the + match type and the match options are available as well by calling + the matchType() and the matchOptions() respectively. + + Please refer to the QRegularExpression documentation for more information + about the Qt regular expression classes. + + \sa QRegularExpression +*/ + +/*! + \class QRegularExpressionMatchIterator + \reentrant + + \brief The QRegularExpressionMatchIterator class provides an iterator on + the results of a global match of a QRegularExpression object against a string. + + \since 5.0 + + \ingroup tools + \ingroup shared + + \keyword regular expression iterator + + A QRegularExpressionMatchIterator object is a forward only Java-like + iterator; it can be obtained by calling the + QRegularExpression::globalMatch() function. A new + QRegularExpressionMatchIterator will be positioned before the first result. + You can then call the hasNext() function to check if there are more + results available; if so, the next() function will return the next + result and advance the iterator. + + Each result is a QRegularExpressionMatch object holding all the information + for that result (including captured substrings). + + For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 30 + + Moreover, QRegularExpressionMatchIterator offers a peekNext() function + to get the next result \e{without} advancing the iterator. + + You can retrieve the QRegularExpression object the subject string was + matched against by calling the regularExpression() function; the + match type and the match options are available as well by calling + the matchType() and the matchOptions() respectively. + + Please refer to the QRegularExpression documentation for more information + about the Qt regular expression classes. + + \sa QRegularExpression, QRegularExpressionMatch +*/ + + +/*! + \enum QRegularExpression::PatternOption + + The PatternOption enum defines modifiers to the way the pattern string + should be interpreted, and therefore the way the pattern matches against a + subject string. + + \value NoPatternOption + No pattern options are set. + + \value CaseInsensitiveOption + The pattern should match against the subject string in a case + insensitive way. This option corresponds to the /i modifier in Perl + regular expressions. + + \value DotMatchesEverythingOption + The dot metacharacter (\c{.}) in the pattern string is allowed to match + any character in the subject string, including newlines (normally, the + dot does not match newlines). This option corresponds to the \c{/s} + modifier in Perl regular expressions. + + \value MultilineOption + The caret (\c{^}) and the dollar (\c{$}) metacharacters in the pattern + string are allowed to match, respectively, immediately after and + immediately before any newline in the subject string, as well as at the + very beginning and at the very end of the subject string. This option + corresponds to the \c{/m} modifier in Perl regular expressions. + + \value ExtendedPatternSyntaxOption + Any whitespace in the pattern string which is not escaped and outside a + character class is ignored. Moreover, an unescaped sharp (\bold{#}) + outside a character class causes all the following characters, until + the first newline (included), to be ignored. This can be used to + increase the readability of a pattern string as well as put comments + inside regular expressions; this is particulary useful if the pattern + string is loaded from a file or written by the user, because in C++ + code it is always possible to use the rules for string literals to put + comments outside the pattern string. This option corresponds to the \c{/x} + modifier in Perl regular expressions. + + \value InvertedGreedinessOption + The greediness of the quantifiers is inverted: \c{*}, \c{+}, \c{?}, + \c{{m,n}}, etc. become lazy, while their lazy versions (\c{*?}, + \c{+?}, \c{??}, \c{{m,n}?}, etc.) become greedy. There is no equivalent + for this option in Perl regular expressions. + + \value DontCaptureOption + The non-named capturing groups do not capture substrings; named + capturing groups still work as intended, as well as the implicit + capturing group number 0 corresponding to the entire match. There is no + equivalent for this option in Perl regular expressions. + + \value UseUnicodePropertiesOption + The meaning of the \c{\w}, \c{\d}, etc., character types, as well as + the meaning of their counterparts (\c{\W}, \c{\D}, etc.), is changed + from matching ASCII charaters only to matching any character with the + corresponding Unicode property. For instance, \c{\d} is changed to + match any character with the Unicode Nd (decimal digit) property; + \c{\w} to match any character with either the Unicode L (letter) or N + (digit) property, plus underscore, and so on. This option corresponds + to the \c{/u} modifier in Perl regular expressions. +*/ + +/*! + \enum QRegularExpression::MatchType + + The MatchType enum defines the type of the match that should be attempted + against the subject string. + + \value NormalMatch + A normal match is done. + + \value PartialPreferCompleteMatch + The pattern string is matched partially against the subject string. If + a partial match is found, then it is recorded, and other matching + alternatives are tried as usual. If a complete match is then found, + then it's preferred to the partial match; in this case only the + complete match is reported. If instead no complete match is found (but + only the partial one), then the partial one is reported. + + \value PartialPreferFirstMatch + The pattern string is matched partially against the subject string. If + a partial match is found, then matching stops and the partial match is + reported. In this case, other matching alternatives (potentially + leading to a complete match) are not tried. Moreover, this match type + assumes that the subject string only a substring of a larger text, and + that (in this text) there are other characters beyond the end of the + subject string. This can lead to surprising results; see the discussion + in the \l{partial matching} section for more details. +*/ + +/*! + \enum QRegularExpression::MatchOption + + \value NoMatchOption + No match options are set. + + \value AnchoredMatchOption + The match is constrained to start exactly at the offset passed to + match() in order to be successful, even if the pattern string does not + contain any metacharacter that anchors the match at that point. +*/ + +/*! + \internal +*/ +static int convertToPcreOptions(QRegularExpression::PatternOptions patternOptions) +{ + int options = 0; + + if (patternOptions & QRegularExpression::CaseInsensitiveOption) + options |= PCRE_CASELESS; + if (patternOptions & QRegularExpression::DotMatchesEverythingOption) + options |= PCRE_DOTALL; + if (patternOptions & QRegularExpression::MultilineOption) + options |= PCRE_MULTILINE; + if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption) + options |= PCRE_EXTENDED; + if (patternOptions & QRegularExpression::InvertedGreedinessOption) + options |= PCRE_UNGREEDY; + if (patternOptions & QRegularExpression::DontCaptureOption) + options |= PCRE_NO_AUTO_CAPTURE; + if (patternOptions & QRegularExpression::UseUnicodePropertiesOption) + options |= PCRE_UCP; + + return options; +} + +/*! + \internal +*/ +static int convertToPcreOptions(QRegularExpression::MatchOptions matchOptions) +{ + int options = 0; + + if (matchOptions & QRegularExpression::AnchoredMatchOption) + options |= PCRE_ANCHORED; + + return options; +} + +struct QRegularExpressionPrivate : QSharedData +{ + QRegularExpressionPrivate(); + ~QRegularExpressionPrivate(); + QRegularExpressionPrivate(const QRegularExpressionPrivate &other); + + void cleanCompiledPattern(); + void compilePattern(); + void getPatternInfo(); + void optimizePattern(); + + QRegularExpressionMatchPrivate *doMatch(const QString &subject, + int offset, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + const QRegularExpressionMatchPrivate *previous = 0) const; + + int captureIndexForName(const QString &name) const; + + QString pattern; + QRegularExpression::PatternOptions patternOptions; + + // *All* of the following members are set managed while holding this mutex, + // except for isDirty which is set to true by QRegularExpression setters + // (right after a detach happened). + // On the other hand, after the compilation and studying, + // it's safe to *use* (i.e. read) them from multiple threads at the same time. + // Therefore, doMatch doesn't need to lock this mutex. + QMutex mutex; + + // The PCRE pointers are reference-counted by the QRegularExpressionPrivate + // objects themselves; when the private is copied (i.e. a detach happened) + // they are set to 0 + pcre16 *compiledPattern; + pcre16_extra *studyData; + const char *errorString; + int errorOffset; + int capturingCount; + unsigned int usedCount; + bool usingCrLfNewlines; + bool isDirty; +}; + +struct QRegularExpressionMatchPrivate : QSharedData +{ + QRegularExpressionMatchPrivate(const QRegularExpression &re, + const QString &subject, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + int capturingCount); + + QRegularExpressionMatch nextMatch() const; + + QRegularExpression regularExpression; + QString subject; + // the capturedOffsets vector contains pairs of (start, end) positions + // for each captured substring + QVector capturedOffsets; + + QRegularExpression::MatchType matchType; + QRegularExpression::MatchOptions matchOptions; + + int capturedCount; + + bool hasMatch; + bool hasPartialMatch; + bool isValid; +}; + +struct QRegularExpressionMatchIteratorPrivate : QSharedData +{ + QRegularExpressionMatchIteratorPrivate(const QRegularExpression re, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + const QRegularExpressionMatch &next); + + bool hasNext() const; + QRegularExpressionMatch next; + QRegularExpression regularExpression; + QRegularExpression::MatchType matchType; + QRegularExpression::MatchOptions matchOptions; +}; + +/*! + \internal +*/ +QRegularExpression::QRegularExpression(QRegularExpressionPrivate &dd) + : d(&dd) +{ +} + +/*! + \internal +*/ +QRegularExpressionPrivate::QRegularExpressionPrivate() + : pattern(), patternOptions(0), + mutex(), + compiledPattern(0), studyData(0), + errorString(0), errorOffset(-1), + capturingCount(0), + usedCount(0), + usingCrLfNewlines(false), + isDirty(true) +{ +} + +/*! + \internal +*/ +QRegularExpressionPrivate::~QRegularExpressionPrivate() +{ + cleanCompiledPattern(); +} + +/*! + \internal + + Copies the private, which means copying only the pattern and the pattern + options. The compiledPattern and the studyData pointers are NOT copied (we + do not own them any more), and in general all the members set when + compiling a pattern are set to default values. isDirty is set back to true + so that the pattern has to be recompiled again. +*/ +QRegularExpressionPrivate::QRegularExpressionPrivate(const QRegularExpressionPrivate &other) + : QSharedData(other), + pattern(other.pattern), patternOptions(other.patternOptions), + mutex(), + compiledPattern(0), studyData(0), + errorString(0), + errorOffset(-1), capturingCount(0), + usedCount(0), + usingCrLfNewlines(false), isDirty(true) +{ +} + +/*! + \internal +*/ +void QRegularExpressionPrivate::cleanCompiledPattern() +{ + pcre16_free(compiledPattern); + pcre16_free_study(studyData); + usedCount = 0; + compiledPattern = 0; + studyData = 0; + usingCrLfNewlines = false; + errorOffset = -1; + capturingCount = 0; +} + +/*! + \internal +*/ +void QRegularExpressionPrivate::compilePattern() +{ + QMutexLocker lock(&mutex); + + if (!isDirty) + return; + + isDirty = false; + cleanCompiledPattern(); + + int options = convertToPcreOptions(patternOptions); + options |= PCRE_UTF16; + + int errorCode; + compiledPattern = pcre16_compile2(pattern.utf16(), options, + &errorCode, &errorString, &errorOffset, 0); + + if (!compiledPattern) + return; + + Q_ASSERT(errorCode == 0); + Q_ASSERT(studyData == 0); // studying (=>optimizing) is always done later + errorOffset = -1; + + getPatternInfo(); +} + +/*! + \internal +*/ +void QRegularExpressionPrivate::getPatternInfo() +{ + Q_ASSERT(compiledPattern); + + pcre16_fullinfo(compiledPattern, 0, PCRE_INFO_CAPTURECOUNT, &capturingCount); + + // detect the settings for the newline + int patternNewlineSetting; + pcre16_fullinfo(compiledPattern, studyData, PCRE_INFO_OPTIONS, &patternNewlineSetting); + patternNewlineSetting &= PCRE_NEWLINE_CR | PCRE_NEWLINE_LF | PCRE_NEWLINE_CRLF + | PCRE_NEWLINE_ANY | PCRE_NEWLINE_ANYCRLF; + if (patternNewlineSetting == 0) { + // no option was specified in the regexp, grab PCRE build defaults + int pcreNewlineSetting; + pcre16_config(PCRE_CONFIG_NEWLINE, &pcreNewlineSetting); + switch (pcreNewlineSetting) { + case 13: + patternNewlineSetting = PCRE_NEWLINE_CR; break; + case 10: + patternNewlineSetting = PCRE_NEWLINE_LF; break; + case 3338: // (13<<8 | 10) + patternNewlineSetting = PCRE_NEWLINE_CRLF; break; + case -2: + patternNewlineSetting = PCRE_NEWLINE_ANYCRLF; break; + case -1: + patternNewlineSetting = PCRE_NEWLINE_ANY; break; + default: + qWarning("QRegularExpressionPrivate::compilePattern(): " + "PCRE_CONFIG_NEWLINE returned an unknown newline"); + break; + } + } + + usingCrLfNewlines = (patternNewlineSetting == PCRE_NEWLINE_CRLF) || + (patternNewlineSetting == PCRE_NEWLINE_ANY) || + (patternNewlineSetting == PCRE_NEWLINE_ANYCRLF); +} + +/*! + \internal +*/ +void QRegularExpressionPrivate::optimizePattern() +{ + Q_ASSERT(compiledPattern); + + QMutexLocker lock(&mutex); + + if (studyData || (++usedCount != OPTIMIZE_AFTER_USE_COUNT)) + return; + + int studyOptions = PCRE_STUDY_JIT_COMPILE; + const char *err; + studyData = pcre16_study(compiledPattern, studyOptions, &err); + + if (!studyData && err) + qWarning("QRegularExpressionPrivate::optimizePattern(): pcre_study failed: %s", err); +} + +/*! + \internal + + Returns the capturing group number for the given name. Duplicated names for + capturing groups are not supported. +*/ +int QRegularExpressionPrivate::captureIndexForName(const QString &name) const +{ + Q_ASSERT(!name.isEmpty()); + + int index = pcre16_get_stringnumber(compiledPattern, name.utf16()); + if (index >= 0) + return index; + + return -1; +} + +/*! + \internal + + Performs a match of type \a matchType on the given \a subject string with + options \a matchOptions and returns the QRegularExpressionMatchPrivate of + the result. It also advances a match if a previous result is given as \a + previous. + + Advancing a match is a tricky algorithm. If the previous match matched a + non-empty string, we just do an ordinary match at the offset position. + + If the previous match matched an empty string, then an anchored, non-empty + match is attempted at the offset position. If that succeeds, then we got + the next match and we can return it. Otherwise, we advance by 1 position + (which can be one or two code units in UTF-16!) and reattempt a "normal" + match. We also have the problem of detecting the current newline format: if + the new advanced offset is pointing to the beginning of a CRLF sequence, we + must advance over it. +*/ +QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString &subject, + int offset, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + const QRegularExpressionMatchPrivate *previous) const +{ + if (offset < 0) + offset += subject.length(); + + QRegularExpression re(*const_cast(this)); + + if (offset < 0 || offset > subject.length()) + return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions, 0); + + if (!compiledPattern) { + qWarning("QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); + return new QRegularExpressionMatchPrivate(re, subject, matchType, matchOptions, 0); + } + + QRegularExpressionMatchPrivate *priv = new QRegularExpressionMatchPrivate(re, subject, + matchType, matchOptions, + capturingCount); + + // this is mutex protected + const_cast(this)->optimizePattern(); + + int pcreOptions = convertToPcreOptions(matchOptions); + + if (matchType == QRegularExpression::PartialPreferCompleteMatch) + pcreOptions |= PCRE_PARTIAL_SOFT; + else if (matchType == QRegularExpression::PartialPreferFirstMatch) + pcreOptions |= PCRE_PARTIAL_HARD; + + bool previousMatchWasEmpty = false; + if (previous && previous->hasMatch && + (previous->capturedOffsets.at(0) == previous->capturedOffsets.at(1))) { + previousMatchWasEmpty = true; + } + + int * const captureOffsets = priv->capturedOffsets.data(); + const int captureOffsetsCount = priv->capturedOffsets.size(); + + const unsigned short * const subjectUtf16 = subject.utf16(); + const int subjectLength = subject.length(); + + int result; + + if (!previousMatchWasEmpty) { + result = pcre16_exec(compiledPattern, studyData, + subjectUtf16, subjectLength, + offset, pcreOptions, + captureOffsets, captureOffsetsCount); + } else { + result = pcre16_exec(compiledPattern, studyData, + subjectUtf16, subjectLength, + offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, + captureOffsets, captureOffsetsCount); + + if (result == PCRE_ERROR_NOMATCH) { + ++offset; + + if (usingCrLfNewlines + && offset < subjectLength + && subjectUtf16[offset - 1] == QLatin1Char('\r') + && subjectUtf16[offset] == QLatin1Char('\n')) { + ++offset; + } else if (offset < subjectLength + && QChar::isLowSurrogate(subjectUtf16[offset])) { + ++offset; + } + + result = pcre16_exec(compiledPattern, studyData, + subjectUtf16, subjectLength, + offset, pcreOptions, + captureOffsets, captureOffsetsCount); + } + } + +#ifdef QREGULAREXPRESSION_DEBUG + qDebug() << "Matching" << pattern << "against" << subject + << offset << matchType << matchOptions << previousMatchWasEmpty + << "result" << result; +#endif + + // result == 0 means not enough space in captureOffsets; should never happen + Q_ASSERT(result != 0); + + if (result > 0) { + // full match + priv->isValid = true; + priv->hasMatch = true; + priv->capturedCount = result; + priv->capturedOffsets.resize(result * 2); + } else { + // no match, partial match or error + priv->hasPartialMatch = (result == PCRE_ERROR_PARTIAL); + priv->isValid = (result == PCRE_ERROR_NOMATCH || result == PCRE_ERROR_PARTIAL); + + if (result == PCRE_ERROR_PARTIAL) { + // partial match: + // leave the start and end capture offsets (i.e. cap(0)) + priv->capturedCount = 1; + priv->capturedOffsets.resize(2); + } else { + // no match or error + priv->capturedCount = 0; + priv->capturedOffsets.clear(); + } + } + + return priv; +} + +/*! + \internal +*/ +QRegularExpressionMatchPrivate::QRegularExpressionMatchPrivate(const QRegularExpression &re, + const QString &subject, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + int capturingCount) + : regularExpression(re), subject(subject), + matchType(matchType), matchOptions(matchOptions), + capturedCount(0), + hasMatch(false), hasPartialMatch(false), isValid(false) +{ + Q_ASSERT(capturingCount >= 0); + const int captureOffsetsCount = (capturingCount + 1) * 3; + capturedOffsets.resize(captureOffsetsCount); +} + + +/*! + \internal +*/ +QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const +{ + Q_ASSERT(isValid); + Q_ASSERT(hasMatch || hasPartialMatch); + + QRegularExpressionMatchPrivate *nextPrivate = regularExpression.d->doMatch(subject, + capturedOffsets.at(1), + matchType, + matchOptions, + this); + return QRegularExpressionMatch(*nextPrivate); +} + +/*! + \internal +*/ +QRegularExpressionMatchIteratorPrivate::QRegularExpressionMatchIteratorPrivate(const QRegularExpression re, + QRegularExpression::MatchType matchType, + QRegularExpression::MatchOptions matchOptions, + const QRegularExpressionMatch &next) + : next(next), + regularExpression(re), + matchType(matchType), matchOptions(matchOptions) +{ +} + +/*! + \internal +*/ +bool QRegularExpressionMatchIteratorPrivate::hasNext() const +{ + return next.isValid() && (next.hasMatch() || next.hasPartialMatch()); +} + +// PUBLIC API + +/*! + Constructs a QRegularExpression object with an empty pattern and no pattern + options. + + \sa setPattern(), setPatternOptions() +*/ +QRegularExpression::QRegularExpression() + : d(new QRegularExpressionPrivate) +{ +} + +/*! + Constructs a QRegularExpression object using the given \a pattern as + pattern and the \a options as the pattern options. + + \sa setPattern(), setPatternOptions() +*/ +QRegularExpression::QRegularExpression(const QString &pattern, PatternOptions options) + : d(new QRegularExpressionPrivate) +{ + d->pattern = pattern; + d->patternOptions = options; +} + +/*! + Constructs a QRegularExpression object as a copy of \a re. + + \sa operator=() +*/ +QRegularExpression::QRegularExpression(const QRegularExpression &re) + : d(re.d) +{ +} + +/*! + Destroys the QRegularExpression object. +*/ +QRegularExpression::~QRegularExpression() +{ +} + +/*! + Assigns the regular expression \a re to this object, and returns a reference + to the copy. Both the pattern and the pattern options are copied. +*/ +QRegularExpression &QRegularExpression::operator=(const QRegularExpression &re) +{ + d = re.d; + return *this; +} + +/*! + \fn void QRegularExpression::swap(QRegularExpression &other) + + Swaps the regular expression \a other with this regular expression. This + operation is very fast and never fails. +*/ + +/*! + Returns the pattern string of the regular expression. + + \sa setPattern(), patternOptions() +*/ +QString QRegularExpression::pattern() const +{ + return d->pattern; +} + +/*! + Sets the pattern string of the regular expression to \a pattern. The + pattern options are left unchanged. + + \sa pattern(), setPatternOptions() +*/ +void QRegularExpression::setPattern(const QString &pattern) +{ + d.detach(); + d->isDirty = true; + d->pattern = pattern; +} + +/*! + Returns the pattern options for the regular expression. + + \sa setPatternOptions(), pattern() +*/ +QRegularExpression::PatternOptions QRegularExpression::patternOptions() const +{ + return d->patternOptions; +} + +/*! + Sets the given \a options as the pattern options of the regular expression. + The pattern string is left unchanged. + + \sa patternOptions(), setPattern() +*/ +void QRegularExpression::setPatternOptions(PatternOptions options) +{ + d.detach(); + d->isDirty = true; + d->patternOptions = options; +} + +/*! + Returns true if the regular expression is a valid regular expression (that + is, it contains no syntax errors, etc.), or false otherwise. Use + errorString() to obtain a textual description of the error. + + \sa errorString(), patternErrorOffset() +*/ +bool QRegularExpression::isValid() const +{ + d.data()->compilePattern(); + return d->compiledPattern; +} + +/*! + Returns a textual description of the error found when checking the validity + of the regular expression, or "no error" if no error was found. + + \sa isValid(), patternErrorOffset() +*/ +QString QRegularExpression::errorString() const +{ + d.data()->compilePattern(); + if (d->errorString) + return QCoreApplication::translate("QRegularExpression", d->errorString, 0, QCoreApplication::UnicodeUTF8); + return QCoreApplication::translate("QRegularExpression", "no error", 0, QCoreApplication::UnicodeUTF8); +} + +/*! + Returns the offset, inside the pattern string, at which an error was found + when checking the validity of the regular expression. If no error was + found, then -1 is returned. + + \sa pattern(), isValid(), errorString() +*/ +int QRegularExpression::patternErrorOffset() const +{ + d.data()->compilePattern(); + return d->errorOffset; +} + +/*! + Attempts to match the regular expression against the given \a subject + string, starting at the position \a offset inside the subject, using a + match of type \a matchType and honoring the given \a matchOptions. + + The returned QRegularExpressionMatch object contains the results of the + match. + + \sa QRegularExpressionMatch, {normal matching} +*/ +QRegularExpressionMatch QRegularExpression::match(const QString &subject, + int offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + d.data()->compilePattern(); + + QRegularExpressionMatchPrivate *priv = d->doMatch(subject, offset, matchType, matchOptions); + return QRegularExpressionMatch(*priv); +} + +/*! + Attempts to perform a global match of the regular expression against the + given \a subject string, starting at the position \a offset inside the + subject, using a match of type \a matchType and honoring the given \a + matchOptions. + + The returned QRegularExpressionMatchIterator is positioned before the + first match result (if any). + + \sa QRegularExpressionMatchIterator, {global matching} +*/ +QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &subject, + int offset, + MatchType matchType, + MatchOptions matchOptions) const +{ + QRegularExpressionMatchIteratorPrivate *priv = + new QRegularExpressionMatchIteratorPrivate(*this, + matchType, + matchOptions, + match(subject, offset, matchType, matchOptions)); + + return QRegularExpressionMatchIterator(*priv); +} + +/*! + Returns true if the regular expression is equal to \a re, or false + otherwise. Two QRegularExpression objects are equal if they have + the same pattern string and the same pattern options. + + \sa operator!=() +*/ +bool QRegularExpression::operator==(const QRegularExpression &re) const +{ + return (pattern() == re.pattern() && patternOptions() == re.patternOptions()); +} + +/*! + \fn bool QRegularExpression::operator!=(const QRegularExpression &re) const + + Returns true if the regular expression is different from \a re, or + false otherwise. + + \sa operator==() +*/ + +/*! + Escapes all characters of \a str so that they no longer have any special + meaning when used as a regular expression pattern string, and returns + the escaped string. For instance: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 26 + + This is very convenient in order to build patterns from arbitrary strings: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 27 + + \note This function implements Perl's quotemeta algorithm and escapes with + a backslash all characters in \a str, except for the characters in the + \c{[A-Z]}, \c{[a-z]} and \c{[0-9]} ranges, as well as the underscore + (\c{_}) character. The only difference with Perl is that a literal NUL + inside \a str is escaped with the sequence \c{"\\\\0"} (backslash + + \c{'0'}), instead of \c{"\\\\\\0"} (backslash + \c{NUL}). +*/ +QString QRegularExpression::escape(const QString &str) +{ + QString result; + const int count = str.size(); + result.reserve(count * 2); + + // everything but [a-zA-Z0-9_] gets escaped, + // cf. perldoc -f quotemeta + for (int i = 0; i < count; ++i) { + const QChar current = str.at(i); + + if (current == QChar::Null) { + // unlike Perl, a literal NUL must be escaped with + // "\\0" (backslash + 0) and not "\\\0" (backslash + NUL), + // because pcre16_compile uses a NUL-terminated string + result.append(QLatin1Char('\\')); + result.append(QLatin1Char('0')); + } else if ( (current < QLatin1Char('a') || current > QLatin1Char('z')) && + (current < QLatin1Char('A') || current > QLatin1Char('Z')) && + (current < QLatin1Char('0') || current > QLatin1Char('9')) && + current != QLatin1Char('_') ) + { + result.append(QLatin1Char('\\')); + result.append(current); + if (current.isHighSurrogate() && i < (count - 1)) + result.append(str.at(++i)); + } else { + result.append(current); + } + } + + result.squeeze(); + return result; +} + +/*! + Destroys the match result. +*/ +QRegularExpressionMatch::~QRegularExpressionMatch() +{ +} + +/*! + Constructs a match result by copying the result of the given \a match. + + \sa operator=() +*/ +QRegularExpressionMatch::QRegularExpressionMatch(const QRegularExpressionMatch &match) + : d(match.d) +{ +} + +/*! + Assigns the match result \a match to this object, and returns a reference + to the copy. +*/ +QRegularExpressionMatch &QRegularExpressionMatch::operator=(const QRegularExpressionMatch &match) +{ + d = match.d; + return *this; +} + +/*! + \fn void QRegularExpressionMatch::swap(QRegularExpressionMatch &other) + + Swaps the match result \a other with this match result. This + operation is very fast and never fails. +*/ + +/*! + \internal +*/ +QRegularExpressionMatch::QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd) + : d(&dd) +{ +} + +/*! + Returns the QRegularExpression object whose match() function returned this + object. + + \sa QRegularExpression::match(), matchType(), matchOptions() +*/ +QRegularExpression QRegularExpressionMatch::regularExpression() const +{ + return d->regularExpression; +} + + +/*! + Returns the match type that was used to get this QRegularExpressionMatch + object, that is, the match type that was passed to + QRegularExpression::match() or QRegularExpression::globalMatch(). + + \sa QRegularExpression::match(), regularExpression(), matchOptions() +*/ +QRegularExpression::MatchType QRegularExpressionMatch::matchType() const +{ + return d->matchType; +} + +/*! + Returns the match options that were used to get this + QRegularExpressionMatch object, that is, the match options that were passed + to QRegularExpression::match() or QRegularExpression::globalMatch(). + + \sa QRegularExpression::match(), regularExpression(), matchType() +*/ +QRegularExpression::MatchOptions QRegularExpressionMatch::matchOptions() const +{ + return d->matchOptions; +} + +/*! + Returns the index of the last capturing group that captured something, + including the implicit capturing group 0. This can be used to extract all + the substrings that were captured: + + \snippet doc/src/snippets/code/src_corelib_tools_qregularexpression.cpp 28 + + Note that some of the capturing groups with an index less than + lastCapturedIndex() could have not matched, and therefore captured nothing. + + If the regular expression did not match, this function returns -1. + + \sa captured(), capturedStart(), capturedEnd(), capturedLength() +*/ +int QRegularExpressionMatch::lastCapturedIndex() const +{ + return d->capturedCount - 1; +} + +/*! + Returns the substring captured by the \a nth capturing group. If the \a nth + capturing group did not capture a string or doesn't exist, returns a null + QString. + + \sa capturedRef(), lastCapturedIndex(), capturedStart(), capturedEnd(), + capturedLength(), QString::isNull() +*/ +QString QRegularExpressionMatch::captured(int nth) const +{ + if (nth < 0 || nth > lastCapturedIndex()) + return QString(); + + int start = capturedStart(nth); + + if (start == -1) // didn't capture + return QString(); + + return d->subject.mid(start, capturedLength(nth)); +} + +/*! + Returns a reference to the substring captured by the \a nth capturing group. + If the \a nth capturing group did not capture a string or doesn't exist, + returns a null QStringRef. + + \sa captured(), lastCapturedIndex(), capturedStart(), capturedEnd(), + capturedLength(), QStringRef::isNull() +*/ +QStringRef QRegularExpressionMatch::capturedRef(int nth) const +{ + if (nth < 0 || nth > lastCapturedIndex()) + return QStringRef(); + + int start = capturedStart(nth); + + if (start == -1) // didn't capture + return QStringRef(); + + return d->subject.midRef(start, capturedLength(nth)); +} + +/*! + Returns the substring captured by the capturing group named \a name. If the + capturing group named \a name did not capture a string or doesn't exist, + returns a null QString. + + \sa capturedRef(), capturedStart(), capturedEnd(), capturedLength(), + QString::isNull() +*/ +QString QRegularExpressionMatch::captured(const QString &name) const +{ + if (name.isEmpty()) { + qWarning("QRegularExpressionMatch::captured: empty capturing group name passed"); + return QString(); + } + int nth = d->regularExpression.d->captureIndexForName(name); + if (nth == -1) + return QString(); + return captured(nth); +} + +/*! + Returns a reference to the string captured by the capturing group named \a + name. If the capturing group named \a name did not capture a string or + doesn't exist, returns a null QStringRef. + + \sa captured(), capturedStart(), capturedEnd(), capturedLength(), + QStringRef::isNull() +*/ +QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const +{ + if (name.isEmpty()) { + qWarning("QRegularExpressionMatch::capturedRef: empty capturing group name passed"); + return QStringRef(); + } + int nth = d->regularExpression.d->captureIndexForName(name); + if (nth == -1) + return QStringRef(); + return capturedRef(nth); +} + +/*! + Returns a list of all strings captured by capturing groups, in the order + the groups themselves appear in the pattern string. +*/ +QStringList QRegularExpressionMatch::capturedTexts() const +{ + QStringList texts; + for (int i = 0; i <= lastCapturedIndex(); ++i) + texts << captured(i); + return texts; +} + +/*! + Returns the offset inside the subject string corresponding to the + starting position of the substring captured by the \a nth capturing group. + If the \a nth capturing group did not capture a string or doesn't exist, + returns -1. + + \sa capturedEnd(), capturedLength(), captured() +*/ +int QRegularExpressionMatch::capturedStart(int nth) const +{ + if (nth < 0 || nth > lastCapturedIndex()) + return -1; + + return d->capturedOffsets.at(nth * 2); +} + +/*! + Returns the length of the substring captured by the \a nth capturing group. + + \note This function returns 0 if the \a nth capturing group did not capture + a string or doesn't exist. + + \sa capturedStart(), capturedEnd(), captured() +*/ +int QRegularExpressionMatch::capturedLength(int nth) const +{ + // bound checking performed by these two functions + return capturedEnd(nth) - capturedStart(nth); +} + +/*! + Returns the offset inside the subject string immediately after the ending + position of the substring captured by the \a nth capturing group. If the \a + nth capturing group did not capture a string or doesn't exist, returns -1. + + \sa capturedStart(), capturedLength(), captured() +*/ +int QRegularExpressionMatch::capturedEnd(int nth) const +{ + if (nth < 0 || nth > lastCapturedIndex()) + return -1; + + return d->capturedOffsets.at(nth * 2 + 1); +} + +/*! + Returns the offset inside the subject string corresponding to the starting + position of the substring captured by the capturing group named \a name. + If the capturing group named \a name did not capture a string or doesn't + exist, returns -1. + + \sa capturedEnd(), capturedLength(), captured() +*/ +int QRegularExpressionMatch::capturedStart(const QString &name) const +{ + if (name.isEmpty()) { + qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed"); + return -1; + } + int nth = d->regularExpression.d->captureIndexForName(name); + if (nth == -1) + return -1; + return capturedStart(nth); +} + +/*! + Returns the offset inside the subject string corresponding to the starting + position of the substring captured by the capturing group named \a name. + + \note This function returns 0 if the capturing group named \a name did not + capture a string or doesn't exist. + + \sa capturedStart(), capturedEnd(), captured() +*/ +int QRegularExpressionMatch::capturedLength(const QString &name) const +{ + if (name.isEmpty()) { + qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed"); + return 0; + } + int nth = d->regularExpression.d->captureIndexForName(name); + if (nth == -1) + return 0; + return capturedLength(nth); +} + +/*! + Returns the offset inside the subject string immediately after the ending + position of the substring captured by the capturing group named \a name. If + the capturing group named \a name did not capture a string or doesn't + exist, returns -1. + + \sa capturedStart(), capturedLength(), captured() +*/ +int QRegularExpressionMatch::capturedEnd(const QString &name) const +{ + if (name.isEmpty()) { + qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed"); + return -1; + } + int nth = d->regularExpression.d->captureIndexForName(name); + if (nth == -1) + return -1; + return capturedEnd(nth); +} + +/*! + Returns true if the regular expression matched against the subject string, + or false otherwise. + + \sa QRegularExpression::match(), hasPartialMatch() +*/ +bool QRegularExpressionMatch::hasMatch() const +{ + return d->hasMatch; +} + +/*! + Returns true if the regular expression partially matched against the + subject string, or false otherwise. + + \note Only a match that explicitely used the one of the partial match types + can yield a partial match. Still, if such a match succeeds totally, this + function will return false, while hasMatch() will return true. + + \sa QRegularExpression::match(), QRegularExpression::MatchType, hasMatch() +*/ +bool QRegularExpressionMatch::hasPartialMatch() const +{ + return d->hasPartialMatch; +} + +/*! + Returns true if the match object was obtained as a result from the + QRegularExpression::match() function invoked on a valid QRegularExpression + object; returns false if the QRegularExpression was invalid. + + \sa QRegularExpression::match(), QRegularExpression::isValid() +*/ +bool QRegularExpressionMatch::isValid() const +{ + return d->isValid; +} + +/*! + \internal +*/ +QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd) + : d(&dd) +{ +} + +/*! + Destroys the QRegularExpressionMatchIterator object. +*/ +QRegularExpressionMatchIterator::~QRegularExpressionMatchIterator() +{ +} + +/*! + Constructs a QRegularExpressionMatchIterator object as a copy of \a + iterator. + + \sa operator=() +*/ +QRegularExpressionMatchIterator::QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator) + : d(iterator.d) +{ +} + +/*! + Assigns the iterator \a iterator to this object, and returns a reference to + the copy. +*/ +QRegularExpressionMatchIterator &QRegularExpressionMatchIterator::operator=(const QRegularExpressionMatchIterator &iterator) +{ + d = iterator.d; + return *this; +} + +/*! + \fn void QRegularExpressionMatchIterator::swap(QRegularExpressionMatchIterator &other) + + Swaps the iterator \a other with this iterator object. This operation is + very fast and never fails. +*/ + +/*! + Returns true if the iterator object was obtained as a result from the + QRegularExpression::globalMatch() function invoked on a valid + QRegularExpression object; returns false if the QRegularExpression was + invalid. + + \sa QRegularExpression::globalMatch(), QRegularExpression::isValid() +*/ +bool QRegularExpressionMatchIterator::isValid() const +{ + return d->next.isValid(); +} + +/*! + Returns true if there is at least one match result ahead of the iterator; + otherwise it returns false. + + \sa next() +*/ +bool QRegularExpressionMatchIterator::hasNext() const +{ + return d->hasNext(); +} + +/*! + Returns the next match result without moving the iterator. + + \note Calling this function when the iterator is at the end of the result + set leads to undefined results. +*/ +QRegularExpressionMatch QRegularExpressionMatchIterator::peekNext() const +{ + if (!hasNext()) + qWarning("QRegularExpressionMatchIterator::peekNext() called on an iterator already at end"); + + return d->next; +} + +/*! + Returns the next match result and advances the iterator by one position. + + \note Calling this function when the iterator is at the end of the result + set leads to undefined results. +*/ +QRegularExpressionMatch QRegularExpressionMatchIterator::next() +{ + if (!hasNext()) { + qWarning("QRegularExpressionMatchIterator::next() called on an iterator already at end"); + return d->next; + } + + QRegularExpressionMatch current = d->next; + d->next = d->next.d.constData()->nextMatch(); + return current; +} + +/*! + Returns the QRegularExpression object whose globalMatch() function returned + this object. + + \sa QRegularExpression::globalMatch(), matchType(), matchOptions() +*/ +QRegularExpression QRegularExpressionMatchIterator::regularExpression() const +{ + return d->regularExpression; +} + +/*! + Returns the match type that was used to get this + QRegularExpressionMatchIterator object, that is, the match type that was + passed to QRegularExpression::globalMatch(). + + \sa QRegularExpression::globalMatch(), regularExpression(), matchOptions() +*/ +QRegularExpression::MatchType QRegularExpressionMatchIterator::matchType() const +{ + return d->matchType; +} + +/*! + Returns the match options that were used to get this + QRegularExpressionMatchIterator object, that is, the match options that + were passed to QRegularExpression::globalMatch(). + + \sa QRegularExpression::globalMatch(), regularExpression(), matchType() +*/ +QRegularExpression::MatchOptions QRegularExpressionMatchIterator::matchOptions() const +{ + return d->matchOptions; +} + +#ifndef QT_NO_DATASTREAM +/*! + \relates QRegularExpression + + Writes the regular expression \a re to stream \a out. + + \sa {Serializing Qt Data Types} +*/ +QDataStream &operator<<(QDataStream &out, const QRegularExpression &re) +{ + out << re.pattern() << quint32(re.patternOptions()); + return out; +} + +/*! + \relates QRegularExpression + + Reads a regular expression from stream \a in into \a re. + + \sa {Serializing Qt Data Types} +*/ +QDataStream &operator>>(QDataStream &in, QRegularExpression &re) +{ + QString pattern; + quint32 patternOptions; + in >> pattern >> patternOptions; + re.setPattern(pattern); + re.setPatternOptions(QRegularExpression::PatternOptions(patternOptions)); + return in; +} +#endif + +#ifndef QT_NO_DEBUG_STREAM +/*! + \relates QRegularExpression + + Writes the regular expression \a re into the debug object \a debug for + debugging purposes. + + \sa {Debugging Techniques} +*/ +QDebug operator<<(QDebug debug, const QRegularExpression &re) +{ + debug.nospace() << "QRegularExpression(" << re.pattern() << ", " << re.patternOptions() << ")"; + return debug.space(); +} + +/*! + \relates QRegularExpressionMatch + + Writes the match object \a match into the debug object \a debug for + debugging purposes. + + \sa {Debugging Techniques} +*/ +QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match) +{ + debug.nospace() << "QRegularExpressionMatch("; + + if (!match.isValid()) { + debug << "Invalid)"; + return debug.space(); + } + + debug << "Valid"; + + if (match.hasMatch()) { + debug << ", has match: "; + for (int i = 0; i <= match.lastCapturedIndex(); ++i) { + debug << i + << ":(" << match.capturedStart(i) << ", " << match.capturedEnd(i) + << ", " << match.captured(i) << ")"; + if (i < match.lastCapturedIndex()) + debug << ", "; + } + } else if (match.hasPartialMatch()) { + debug << ", has partial match: (" + << match.capturedStart(0) << ", " + << match.capturedEnd(0) << ", " + << match.captured(0) << ")"; + } else { + debug << ", no match"; + } + + debug << ")"; + + return debug.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h new file mode 100644 index 0000000000..c9bcb1e7ba --- /dev/null +++ b/src/corelib/tools/qregularexpression.h @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QREGULAREXPRESSION_H +#define QREGULAREXPRESSION_H + +#ifndef QT_NO_REGEXP + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QRegularExpressionMatch; +class QRegularExpressionMatchIterator; +struct QRegularExpressionPrivate; + +class Q_CORE_EXPORT QRegularExpression +{ +public: + enum PatternOption { + NoPatternOption = 0x0000, + CaseInsensitiveOption = 0x0001, + DotMatchesEverythingOption = 0x0002, + MultilineOption = 0x0004, + ExtendedPatternSyntaxOption = 0x0008, + InvertedGreedinessOption = 0x0010, + DontCaptureOption = 0x0020, + UseUnicodePropertiesOption = 0x0040 + }; + Q_DECLARE_FLAGS(PatternOptions, PatternOption) + + PatternOptions patternOptions() const; + void setPatternOptions(PatternOptions options); + + QRegularExpression(); + explicit QRegularExpression(const QString &pattern, PatternOptions options = NoPatternOption); + QRegularExpression(const QRegularExpression &re); + ~QRegularExpression(); + QRegularExpression &operator=(const QRegularExpression &re); + +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegularExpression &operator=(QRegularExpression &&re) + { d.swap(re.d); return *this; } +#endif + + inline void swap(QRegularExpression &re) { d.swap(re.d); } + + QString pattern() const; + void setPattern(const QString &pattern); + + bool isValid() const; + int patternErrorOffset() const; + QString errorString() const; + + enum MatchType { + NormalMatch = 0, + PartialPreferCompleteMatch, + PartialPreferFirstMatch + }; + + enum MatchOption { + NoMatchOption = 0x0000, + AnchoredMatchOption = 0x0001 + }; + Q_DECLARE_FLAGS(MatchOptions, MatchOption) + + QRegularExpressionMatch match(const QString &subject, + int offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; + + QRegularExpressionMatchIterator globalMatch(const QString &subject, + int offset = 0, + MatchType matchType = NormalMatch, + MatchOptions matchOptions = NoMatchOption) const; + + static QString escape(const QString &str); + + bool operator==(const QRegularExpression &re) const; + inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); } + +private: + friend struct QRegularExpressionPrivate; + friend class QRegularExpressionMatch; + friend struct QRegularExpressionMatchPrivate; + friend class QRegularExpressionMatchIterator; + + QRegularExpression(QRegularExpressionPrivate &dd); + QExplicitlySharedDataPointer d; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::PatternOptions) +Q_DECLARE_OPERATORS_FOR_FLAGS(QRegularExpression::MatchOptions) +Q_DECLARE_TYPEINFO(QRegularExpression, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegularExpression &re); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegularExpression &re); +#endif + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpression &re); +#endif + +struct QRegularExpressionMatchPrivate; + +class Q_CORE_EXPORT QRegularExpressionMatch +{ +public: + ~QRegularExpressionMatch(); + QRegularExpressionMatch(const QRegularExpressionMatch &match); + QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match); + +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) + { d.swap(match.d); return *this; } +#endif + inline void swap(QRegularExpressionMatch &match) { d.swap(match.d); } + + QRegularExpression regularExpression() const; + QRegularExpression::MatchType matchType() const; + QRegularExpression::MatchOptions matchOptions() const; + + bool hasMatch() const; + bool hasPartialMatch() const; + + bool isValid() const; + + int lastCapturedIndex() const; + + QString captured(int nth = 0) const; + QStringRef capturedRef(int nth = 0) const; + + QString captured(const QString &name) const; + QStringRef capturedRef(const QString &name) const; + + QStringList capturedTexts() const; + + int capturedStart(int nth = 0) const; + int capturedLength(int nth = 0) const; + int capturedEnd(int nth = 0) const; + + int capturedStart(const QString &name) const; + int capturedLength(const QString &name) const; + int capturedEnd(const QString &name) const; + +private: + friend class QRegularExpression; + friend struct QRegularExpressionMatchPrivate; + friend class QRegularExpressionMatchIterator; + + QRegularExpressionMatch(QRegularExpressionMatchPrivate &dd); + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(QRegularExpressionMatch, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpressionMatch &match); +#endif + +struct QRegularExpressionMatchIteratorPrivate; + +class Q_CORE_EXPORT QRegularExpressionMatchIterator +{ +public: + ~QRegularExpressionMatchIterator(); + QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator); + QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator); +#ifdef Q_COMPILER_RVALUE_REFS + inline QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) + { d.swap(iterator.d); return *this; } +#endif + void swap(QRegularExpressionMatchIterator &iterator) { d.swap(iterator.d); } + + bool isValid() const; + + bool hasNext() const; + QRegularExpressionMatch next(); + QRegularExpressionMatch peekNext() const; + + QRegularExpression regularExpression() const; + QRegularExpression::MatchType matchType() const; + QRegularExpression::MatchOptions matchOptions() const; + +private: + friend class QRegularExpression; + + QRegularExpressionMatchIterator(QRegularExpressionMatchIteratorPrivate &dd); + QSharedDataPointer d; +}; + +Q_DECLARE_TYPEINFO(QRegularExpressionMatchIterator, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QRegularExpression) + +QT_END_HEADER + +#endif // QT_NO_REGEXP + +#endif // QREGULAREXPRESSION_H diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 3740975b12..250789a969 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -30,6 +30,7 @@ HEADERS += \ tools/qqueue.h \ tools/qrect.h \ tools/qregexp.h \ + tools/qregularexpression.h \ tools/qringbuffer_p.h \ tools/qrefcount.h \ tools/qscopedpointer.h \ @@ -75,6 +76,7 @@ SOURCES += \ tools/qcontiguouscache.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ + tools/qregularexpression.cpp \ tools/qrefcount.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ @@ -105,6 +107,12 @@ contains(QT_CONFIG,icu) { DEFINES += QT_USE_ICU } +pcre { + include($$PWD/../../3rdparty/pcre.pri) +} else { + LIBS_PRIVATE += -lpcre16 +} + DEFINES += HB_EXPORT=Q_CORE_EXPORT INCLUDEPATH += ../3rdparty/harfbuzz/src HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/tools/qregularexpression/.gitignore new file mode 100644 index 0000000000..4a224d26fc --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/.gitignore @@ -0,0 +1 @@ +tst_qregularexpression diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro new file mode 100644 index 0000000000..bce6643be6 --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qregularexpression +QT = core testlib +SOURCES = tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp new file mode 100644 index 0000000000..93cb6823cd --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -0,0 +1,1150 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +Q_DECLARE_METATYPE(QRegularExpression::PatternOptions) +Q_DECLARE_METATYPE(QRegularExpression::MatchType) +Q_DECLARE_METATYPE(QRegularExpression::MatchOptions) + +class tst_QRegularExpression : public QObject +{ + Q_OBJECT + +private slots: + void gettersSetters_data(); + void gettersSetters(); + void escape_data(); + void escape(); + void validity_data(); + void validity(); + void patternOptions_data(); + void patternOptions(); + void normalMatch_data(); + void normalMatch(); + void partialMatch_data(); + void partialMatch(); + void globalMatch_data(); + void globalMatch(); + void serialize_data(); + void serialize(); + +private: + void provideRegularExpressions(); +}; + +struct Match +{ + Match() + { + clear(); + } + + void clear() + { + isValid = false; + hasMatch = false; + hasPartialMatch = false; + captured.clear(); + namedCaptured.clear(); + } + + bool isValid; + bool hasMatch; + bool hasPartialMatch; + QStringList captured; + QHash namedCaptured; +}; + +Q_DECLARE_METATYPE(Match) +Q_DECLARE_METATYPE(QList) + +bool operator==(const QRegularExpressionMatch &rem, const Match &m) +{ + if (rem.isValid() != m.isValid) + return false; + if (!rem.isValid()) + return true; + if ((rem.hasMatch() != m.hasMatch) || (rem.hasPartialMatch() != m.hasPartialMatch)) + return false; + if (rem.hasMatch() || rem.hasPartialMatch()) { + if (rem.lastCapturedIndex() != (m.captured.size() - 1)) + return false; + for (int i = 0; i <= rem.lastCapturedIndex(); ++i) { + QString remCaptured = rem.captured(i); + QString mCaptured = m.captured.at(i); + if (remCaptured != mCaptured + || remCaptured.isNull() != mCaptured.isNull() + || remCaptured.isEmpty() != mCaptured.isEmpty()) { + return false; + } + } + + Q_FOREACH (const QString &name, m.namedCaptured.keys()) { + if (rem.captured(name) != m.namedCaptured.value(name)) + return false; + } + } + + return true; +} + +bool operator==(const Match &m, const QRegularExpressionMatch &rem) +{ + return operator==(rem, m); +} + +bool operator!=(const QRegularExpressionMatch &rem, const Match &m) +{ + return !operator==(rem, m); +} + +bool operator!=(const Match &m, const QRegularExpressionMatch &rem) +{ + return !operator==(m, rem); +} + + +bool operator==(const QRegularExpressionMatchIterator &iterator, const QList &expectedMatchList) +{ + QRegularExpressionMatchIterator i = iterator; + if (i.isValid() != (!expectedMatchList.isEmpty())) + return false; + + foreach (const Match &expectedMatch, expectedMatchList) + { + if (!i.hasNext()) + return false; + + QRegularExpressionMatch match = i.next(); + if (match != expectedMatch) + return false; + } + + if (i.hasNext()) + return false; + + return true; +} + +bool operator==(const QList &expectedMatchList, const QRegularExpressionMatchIterator &iterator) +{ + return operator==(iterator, expectedMatchList); +} + +bool operator!=(const QRegularExpressionMatchIterator &iterator, const QList &expectedMatchList) +{ + return !operator==(iterator, expectedMatchList); +} + +bool operator!=(const QList &expectedMatchList, const QRegularExpressionMatchIterator &iterator) +{ + return !operator==(expectedMatchList, iterator); +} + +void consistencyCheck(const QRegularExpressionMatch &match) +{ + QVERIFY(match.isValid() == match.regularExpression().isValid()); + + if (match.isValid()) { + QVERIFY(!(match.hasMatch() && match.hasPartialMatch())); + + if (match.hasMatch() || match.hasPartialMatch()) { + QVERIFY(match.lastCapturedIndex() >= 0); + if (match.hasPartialMatch()) + QVERIFY(match.lastCapturedIndex() == 0); + + for (int i = 0; i <= match.lastCapturedIndex(); ++i) { + int startPos = match.capturedStart(i); + int endPos = match.capturedEnd(i); + int length = match.capturedLength(i); + QString captured = match.captured(i); + QStringRef capturedRef = match.capturedRef(i); + + if (!captured.isNull()) { + QVERIFY(startPos >= 0); + QVERIFY(endPos >= 0); + QVERIFY(length >= 0); + QVERIFY(endPos >= startPos); + QVERIFY((endPos - startPos) == length); + QVERIFY(captured == capturedRef); + } else { + QVERIFY(startPos == -1); + QVERIFY(endPos == -1); + QVERIFY((endPos - startPos) == length); + QVERIFY(capturedRef.isNull()); + } + } + } + } else { + QVERIFY(!match.hasMatch()); + QVERIFY(!match.hasPartialMatch()); + QVERIFY(match.captured(0).isNull()); + QVERIFY(match.capturedStart(0) == -1); + QVERIFY(match.capturedEnd(0) == -1); + QVERIFY(match.capturedLength(0) == 0); + } +} + +void consistencyCheck(const QRegularExpressionMatchIterator &iterator) +{ + QRegularExpressionMatchIterator i(iterator); // make a copy, we modify it + if (i.isValid()) { + while (i.hasNext()) { + QRegularExpressionMatch peeked = i.peekNext(); + QRegularExpressionMatch match = i.next(); + consistencyCheck(peeked); + consistencyCheck(match); + QVERIFY(match.isValid()); + QVERIFY(match.hasMatch() || match.hasPartialMatch()); + QCOMPARE(i.regularExpression(), match.regularExpression()); + QCOMPARE(i.matchOptions(), match.matchOptions()); + QCOMPARE(i.matchType(), match.matchType()); + + QVERIFY(peeked.isValid() == match.isValid()); + QVERIFY(peeked.hasMatch() == match.hasMatch()); + QVERIFY(peeked.hasPartialMatch() == match.hasPartialMatch()); + QVERIFY(peeked.lastCapturedIndex() == match.lastCapturedIndex()); + for (int i = 0; i <= peeked.lastCapturedIndex(); ++i) { + QVERIFY(peeked.captured(i) == match.captured(i)); + QVERIFY(peeked.capturedStart(i) == match.capturedStart(i)); + QVERIFY(peeked.capturedEnd(i) == match.capturedEnd(i)); + } + } + } else { + QVERIFY(!i.hasNext()); + QRegularExpressionMatch peeked = i.peekNext(); + QRegularExpressionMatch match = i.next(); + consistencyCheck(peeked); + consistencyCheck(match); + QVERIFY(!match.isValid()); + QVERIFY(!peeked.isValid()); + } + +} + +void tst_QRegularExpression::provideRegularExpressions() +{ + QTest::addColumn("pattern"); + QTest::addColumn("patternOptions"); + + QTest::newRow("emptynull01") << QString() + << QRegularExpression::PatternOptions(0); + QTest::newRow("emptynull02") << QString() + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption + | QRegularExpression::DotMatchesEverythingOption + | QRegularExpression::MultilineOption); + QTest::newRow("emptynull03") << "" + << QRegularExpression::PatternOptions(0); + QTest::newRow("emptynull04") << "" + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption + | QRegularExpression::DotMatchesEverythingOption + | QRegularExpression::MultilineOption); + + QTest::newRow("regexp01") << "a pattern" + << QRegularExpression::PatternOptions(0); + QTest::newRow("regexp02") << "^a (.*) more complicated(?

pattern)$" + << QRegularExpression::PatternOptions(0); + QTest::newRow("regexp03") << "(?:a) pAttErN" + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption); + QTest::newRow("regexp04") << "a\nmultiline\npattern" + << QRegularExpression::PatternOptions(QRegularExpression::MultilineOption); + QTest::newRow("regexp05") << "an extended # IGNOREME\npattern" + << QRegularExpression::PatternOptions(QRegularExpression::ExtendedPatternSyntaxOption); + QTest::newRow("regexp06") << "a [sS]ingleline .* match" + << QRegularExpression::PatternOptions(QRegularExpression::DotMatchesEverythingOption); + QTest::newRow("regexp07") << "multiple.*options" + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption + | QRegularExpression::DotMatchesEverythingOption + | QRegularExpression::MultilineOption + | QRegularExpression::DontCaptureOption + | QRegularExpression::InvertedGreedinessOption); + + QTest::newRow("unicode01") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$") + << QRegularExpression::PatternOptions(0); + QTest::newRow("unicode02") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$") + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption + | QRegularExpression::DotMatchesEverythingOption + | QRegularExpression::InvertedGreedinessOption); + QTest::newRow("unicode03") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f") + << QRegularExpression::PatternOptions(0); + QTest::newRow("unicode04") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f") + << QRegularExpression::PatternOptions(QRegularExpression::CaseInsensitiveOption + | QRegularExpression::DotMatchesEverythingOption + | QRegularExpression::InvertedGreedinessOption); +} + +void tst_QRegularExpression::gettersSetters_data() +{ + provideRegularExpressions(); +} + +void tst_QRegularExpression::gettersSetters() +{ + QFETCH(QString, pattern); + QFETCH(QRegularExpression::PatternOptions, patternOptions); + { + QRegularExpression re; + re.setPattern(pattern); + QCOMPARE(re.pattern(), pattern); + QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption); + } + { + QRegularExpression re; + re.setPatternOptions(patternOptions); + QCOMPARE(re.pattern(), QString()); + QCOMPARE(re.patternOptions(), patternOptions); + } + { + QRegularExpression re(pattern); + QCOMPARE(re.pattern(), pattern); + QCOMPARE(re.patternOptions(), QRegularExpression::NoPatternOption); + } + { + QRegularExpression re(pattern, patternOptions); + QCOMPARE(re.pattern(), pattern); + QCOMPARE(re.patternOptions(), patternOptions); + } + { + QRegularExpression re(pattern, patternOptions); + QRegularExpression re2(pattern, patternOptions); + QVERIFY(re == re2); + } +} + +void tst_QRegularExpression::escape_data() +{ + QTest::addColumn("string"); + QTest::addColumn("escaped"); + QTest::newRow("escape01") << "a normal pattern" + << "a\\ normal\\ pattern"; + + QTest::newRow("escape02") << "abcdefghijklmnopqrstuvzABCDEFGHIJKLMNOPQRSTUVZ1234567890_" + << "abcdefghijklmnopqrstuvzABCDEFGHIJKLMNOPQRSTUVZ1234567890_"; + + QTest::newRow("escape03") << "^\\ba\\b.*(?reg|exp)$" + << "\\^\\\\ba\\\\b\\.\\*\\(\\?\\reg\\|exp\\)\\$"; + + QString nulString("abcXabcXXabc"); + nulString[3] = nulString[7] = nulString[8] = QChar(0, 0); + QTest::newRow("NUL") << nulString + << "abc\\0abc\\0\\0abc"; + + QTest::newRow("unicode01") << QString::fromUtf8("^s[ome] latin-1 \xc3\x80\xc3\x88\xc3\x8c\xc3\x92\xc3\x99 chars$") + << QString::fromUtf8("\\^s\\[ome\\]\\ latin\\-1\\ \\\xc3\x80\\\xc3\x88\\\xc3\x8c\\\xc3\x92\\\xc3\x99\\ chars\\$"); + QTest::newRow("unicode02") << QString::fromUtf8("Unicode \xf0\x9d\x85\x9d \xf0\x9d\x85\x9e\xf0\x9d\x85\x9f") + << QString::fromUtf8("Unicode\\ \\\xf0\x9d\x85\x9d\\ \\\xf0\x9d\x85\x9e\\\xf0\x9d\x85\x9f"); + + QString unicodeAndNulString = QString::fromUtf8("^\xc3\x80\xc3\x88\xc3\x8cN\xc3\x92NN\xc3\x99 chars$"); + unicodeAndNulString[4] = unicodeAndNulString[6] = unicodeAndNulString[7] = QChar(0, 0); + QTest::newRow("unicode03") << unicodeAndNulString + << QString::fromUtf8("\\^\\\xc3\x80\\\xc3\x88\\\xc3\x8c\\0\\\xc3\x92\\0\\0\\\xc3\x99\\ chars\\$"); +} + +void tst_QRegularExpression::escape() +{ + QFETCH(QString, string); + QFETCH(QString, escaped); + QCOMPARE(QRegularExpression::escape(string), escaped); + QRegularExpression re(escaped); + QCOMPARE(re.isValid(), true); +} + +void tst_QRegularExpression::validity_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("validity"); + + QTest::newRow("valid01") << "a pattern" << true; + QTest::newRow("valid02") << "(a|pattern)" << true; + QTest::newRow("valid03") << "a [pP]attern" << true; + QTest::newRow("valid04") << "^(?

a).*(?pattern)$" << true; + QTest::newRow("valid05") << "a \\P{Ll}attern" << true; + + QTest::newRow("invalid01") << "a pattern\\" << false; + QTest::newRow("invalid02") << "(a|pattern" << false; + QTest::newRow("invalid03") << "a \\P{BLAH}attern" << false; + + QString pattern; + // 0xD800 (high surrogate) not followed by a low surrogate + pattern = "abcdef"; + pattern[3] = QChar(0x00, 0xD8); + QTest::newRow("invalidUnicode01") << pattern << false; +} + +void tst_QRegularExpression::validity() +{ + QFETCH(QString, pattern); + QFETCH(bool, validity); + QRegularExpression re(pattern); + QCOMPARE(re.isValid(), validity); + if (!validity) + QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); + QRegularExpressionMatch match = re.match("a pattern"); + QCOMPARE(match.isValid(), validity); + consistencyCheck(match); + + if (!validity) + QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionPrivate::doMatch(): called on an invalid QRegularExpression object"); + QRegularExpressionMatchIterator iterator = re.globalMatch("a pattern"); + QCOMPARE(iterator.isValid(), validity); +} + +void tst_QRegularExpression::patternOptions_data() +{ + QTest::addColumn("regexp"); + QTest::addColumn("subject"); + QTest::addColumn("match"); + + // none of these would successfully match if the respective + // pattern option is not set + + Match m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << QString::fromUtf8("AbC\xc3\xa0"); + QTest::newRow("/i") << QRegularExpression(QString::fromUtf8("abc\xc3\x80"), QRegularExpression::CaseInsensitiveOption) + << QString::fromUtf8("AbC\xc3\xa0") + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "abc123\n678def"; + QTest::newRow("/s") << QRegularExpression("\\Aabc.*def\\z", QRegularExpression::DotMatchesEverythingOption) + << "abc123\n678def" + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "jumped over"; + QTest::newRow("/m") << QRegularExpression("^\\w+ \\w+$", QRegularExpression::MultilineOption) + << "the quick fox\njumped over\nthe lazy\ndog" + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "abc 123456"; + QTest::newRow("/x") << QRegularExpression("\\w+ # a word\n" + "\\ # a space\n" + "\\w+ # another word", + QRegularExpression::ExtendedPatternSyntaxOption) + << "abc 123456 def" + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "the quick fox" << "the" << "quick fox"; + QTest::newRow("/U") << QRegularExpression("(.+) (.+?)", QRegularExpression::InvertedGreedinessOption) + << "the quick fox" + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "the quick fox" << "quick"; + m.namedCaptured["named"] = "quick"; + QTest::newRow("no cap") << QRegularExpression("(\\w+) (?\\w+) (\\w+)", QRegularExpression::DontCaptureOption) + << "the quick fox" + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << QString::fromUtf8("abc\xc3\x80\xc3\xa0 12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98") + << QString::fromUtf8("abc\xc3\x80\xc3\xa0") + << QString::fromUtf8("12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98"); + QTest::newRow("unicode properties") << QRegularExpression("(\\w+) (\\d+)", QRegularExpression::UseUnicodePropertiesOption) + << QString::fromUtf8("abc\xc3\x80\xc3\xa0 12\xdb\xb1\xdb\xb2\xf0\x9d\x9f\x98") + << m; +} + +void tst_QRegularExpression::patternOptions() +{ + QFETCH(QRegularExpression, regexp); + QFETCH(QString, subject); + QFETCH(Match, match); + + QRegularExpressionMatch m = regexp.match(subject); + consistencyCheck(m); + QVERIFY(m == match); +} + +void tst_QRegularExpression::normalMatch_data() +{ + QTest::addColumn("regexp"); + QTest::addColumn("subject"); + QTest::addColumn("offset"); + QTest::addColumn("matchOptions"); + QTest::addColumn("match"); + + Match m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "string" << "string"; + QTest::newRow("match01") << QRegularExpression("(\\bstring\\b)") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "a string" << "a" << "string"; + QTest::newRow("match02") << QRegularExpression("(\\w+) (\\w+)") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "a string" << "a" << "string"; + m.namedCaptured["article"] = "a"; + m.namedCaptured["noun"] = "string"; + QTest::newRow("match03") << QRegularExpression("(?
\\w+) (?\\w+)") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << " string" << QString() << "string"; + QTest::newRow("match04") << QRegularExpression("(\\w+)? (\\w+)") + << " string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << " string" << QString("") << "string"; + QTest::newRow("match05") << QRegularExpression("(\\w*) (\\w+)") + << " string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "c123def" << "c12" << "3" << "def"; + QTest::newRow("match06") << QRegularExpression("(\\w*)(\\d+)(\\w*)") + << "abc123def" + << 2 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << QString(""); + QTest::newRow("match07") << QRegularExpression("\\w*") + << "abc123def" + << 9 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << QString("a string") << QString("a string") << QString(""); + QTest::newRow("match08") << QRegularExpression("(.*)(.*)") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << QString("a string") << QString("") << QString("a string"); + QTest::newRow("match09") << QRegularExpression("(.*?)(.*)") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + // *** + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch01") << QRegularExpression("\\d+") + << "a string" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch02") << QRegularExpression("(\\w+) (\\w+)") + << "a string" + << 1 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch03") << QRegularExpression("\\w+") + << "abc123def" + << 9 + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + // *** + + m.clear(); + m.isValid = true; + QTest::newRow("anchoredmatch01") << QRegularExpression("\\d+") + << "abc123def" + << 0 + << QRegularExpression::MatchOptions(QRegularExpression::AnchoredMatchOption) + << m; +} + + +void tst_QRegularExpression::normalMatch() +{ + QFETCH(QRegularExpression, regexp); + QFETCH(QString, subject); + QFETCH(int, offset); + QFETCH(QRegularExpression::MatchOptions, matchOptions); + QFETCH(Match, match); + + QRegularExpressionMatch m = regexp.match(subject, offset, QRegularExpression::NormalMatch, matchOptions); + consistencyCheck(m); + QVERIFY(m == match); +} + + +void tst_QRegularExpression::partialMatch_data() +{ + QTest::addColumn("regexp"); + QTest::addColumn("subject"); + QTest::addColumn("offset"); + QTest::addColumn("matchType"); + QTest::addColumn("matchOptions"); + QTest::addColumn("match"); + + Match m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "str"; + QTest::newRow("softmatch01") << QRegularExpression("string") + << "a str" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << " str"; + QTest::newRow("softmatch02") << QRegularExpression("\\bstring\\b") + << "a str" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << " str"; + QTest::newRow("softmatch03") << QRegularExpression("(\\bstring\\b)") + << "a str" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "8 Dec 19"; + QTest::newRow("softmatch04") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$") + << "8 Dec 19" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "8 Dec 1985" << "8" << "Dec" << "1985"; + QTest::newRow("softmatch05") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$") + << "8 Dec 1985" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured << "def"; + QTest::newRow("softmatch06") << QRegularExpression("abc\\w+X|def") + << "abcdef" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "abcdef"; + QTest::newRow("softmatch07") << QRegularExpression("abc\\w+X|defY") + << "abcdef" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "def"; + QTest::newRow("softmatch08") << QRegularExpression("abc\\w+X|defY") + << "abcdef" + << 1 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + // *** + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "str"; + QTest::newRow("hardmatch01") << QRegularExpression("string") + << "a str" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << " str"; + QTest::newRow("hardmatch02") << QRegularExpression("\\bstring\\b") + << "a str" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << " str"; + QTest::newRow("hardmatch03") << QRegularExpression("(\\bstring\\b)") + << "a str" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "8 Dec 19"; + QTest::newRow("hardmatch04") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$") + << "8 Dec 19" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "8 Dec 1985"; + QTest::newRow("hardmatch05") << QRegularExpression("^(\\d{1,2}) (\\w{3}) (\\d{4})$") + << "8 Dec 1985" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "abcdef"; + QTest::newRow("hardmatch06") << QRegularExpression("abc\\w+X|def") + << "abcdef" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "abcdef"; + QTest::newRow("hardmatch07") << QRegularExpression("abc\\w+X|defY") + << "abcdef" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "def"; + QTest::newRow("hardmatch08") << QRegularExpression("abc\\w+X|defY") + << "abcdef" + << 1 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "ab"; + QTest::newRow("hardmatch09") << QRegularExpression("abc|ab") + << "ab" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "abc"; + QTest::newRow("hardmatch10") << QRegularExpression("abc(def)?") + << "abc" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; m.hasPartialMatch = true; + m.captured << "abc"; + QTest::newRow("hardmatch11") << QRegularExpression("(abc)*") + << "abc" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + + // *** + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch01") << QRegularExpression("abc\\w+X|defY") + << "123456" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch02") << QRegularExpression("abc\\w+X|defY") + << "123456" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch03") << QRegularExpression("abc\\w+X|defY") + << "ab123" + << 0 + << QRegularExpression::PartialPreferCompleteMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + + m.clear(); + m.isValid = true; + QTest::newRow("nomatch04") << QRegularExpression("abc\\w+X|defY") + << "ab123" + << 0 + << QRegularExpression::PartialPreferFirstMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << m; + +} + +void tst_QRegularExpression::partialMatch() +{ + QFETCH(QRegularExpression, regexp); + QFETCH(QString, subject); + QFETCH(int, offset); + QFETCH(QRegularExpression::MatchType, matchType); + QFETCH(QRegularExpression::MatchOptions, matchOptions); + QFETCH(Match, match); + + QRegularExpressionMatch m = regexp.match(subject, offset, matchType, matchOptions); + consistencyCheck(m); + QVERIFY(m == match); +} + +void tst_QRegularExpression::globalMatch_data() +{ + QTest::addColumn("regexp"); + QTest::addColumn("subject"); + QTest::addColumn("offset"); + QTest::addColumn("matchType"); + QTest::addColumn("matchOptions"); + QTest::addColumn >("matchList"); + + QList matchList; + Match m; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + QTest::newRow("globalmatch01") << QRegularExpression("\\w+") + << "the quick fox" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the" << "t" << "he"; + matchList << m; + m.captured = QStringList() << "quick" << "q" << "uick"; + matchList << m; + m.captured = QStringList() << "fox" << "f" << "ox"; + matchList << m; + QTest::newRow("globalmatch02") << QRegularExpression("(\\w+?)(\\w+)") + << "the quick fox" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "c"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "c"; + matchList << m; + m.captured = QStringList() << "aabb"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures01") << QRegularExpression("a*b*|c") + << "ccaabbd" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures02") << QRegularExpression(".*") + << "the\nquick\nfox" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures03") << QRegularExpression(".*") + << "the\nquick\nfox\n" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures04") << QRegularExpression("(*CRLF).*") + << "the\r\nquick\r\nfox" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures05") << QRegularExpression("(*CRLF).*") + << "the\r\nquick\r\nfox\r\n" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; + + matchList.clear(); + m.clear(); + m.isValid = true; m.hasMatch = true; + m.captured = QStringList() << "the"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "quick"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "fox"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + m.captured = QStringList() << "jumped"; + matchList << m; + m.captured = QStringList() << ""; + matchList << m; + + QTest::newRow("globalmatch_emptycaptures06") << QRegularExpression("(*ANYCRLF).*") + << "the\r\nquick\nfox\rjumped" + << 0 + << QRegularExpression::NormalMatch + << QRegularExpression::MatchOptions(QRegularExpression::NoMatchOption) + << matchList; +} + +void tst_QRegularExpression::globalMatch() +{ + QFETCH(QRegularExpression, regexp); + QFETCH(QString, subject); + QFETCH(int, offset); + QFETCH(QRegularExpression::MatchType, matchType); + QFETCH(QRegularExpression::MatchOptions, matchOptions); + QFETCH(QList, matchList); + + QRegularExpressionMatchIterator iterator = regexp.globalMatch(subject, offset, matchType, matchOptions); + consistencyCheck(iterator); + QVERIFY(iterator == matchList); +} + +void tst_QRegularExpression::serialize_data() +{ + provideRegularExpressions(); +} + +void tst_QRegularExpression::serialize() +{ + QFETCH(QString, pattern); + QFETCH(QRegularExpression::PatternOptions, patternOptions); + QRegularExpression outRe(pattern, patternOptions); + QByteArray buffer; + { + QDataStream out(&buffer, QIODevice::WriteOnly); + out << outRe; + } + QRegularExpression inRe; + { + QDataStream in(&buffer, QIODevice::ReadOnly); + in >> inRe; + } + QCOMPARE(inRe, outRe); +} + +QTEST_APPLESS_MAIN(tst_QRegularExpression) + +#include "tst_qregularexpression.moc" + diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index 89bb3bc416..d8961559e5 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -25,6 +25,7 @@ SUBDIRS=\ qqueue \ qrect \ qregexp \ + qregularexpression \ qringbuffer \ qscopedpointer \ qscopedvaluerollback \ -- cgit v1.2.3 From aea65cbaa4fd889129d7945600dad3277f9c6d9b Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 7 Feb 2012 23:56:40 +0000 Subject: QRegularExpression: QDebug support for pattern options Added the proper QDebug operator to debug the QRegularExpression::PatternOptions flags. Change-Id: Icd00e93a0c6cc4345db528d494fc176624f7b7a2 Reviewed-by: hjk Reviewed-by: Lars Knoll --- src/corelib/tools/qregularexpression.cpp | 37 ++++++++++++++++++++++++++++++++ src/corelib/tools/qregularexpression.h | 1 + 2 files changed, 38 insertions(+) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 488a454aaa..7fbbfaa9ef 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1976,6 +1976,43 @@ QDebug operator<<(QDebug debug, const QRegularExpression &re) return debug.space(); } +/*! + \relates QRegularExpression + + Writes the pattern options \a patternOptions into the debug object \a debug + for debugging purposes. + + \sa {Debugging Techniques} +*/ +QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions) +{ + QStringList flags; + + if (patternOptions == QRegularExpression::NoPatternOption) { + flags << QLatin1String("NoPatternOption"); + } else { + if (patternOptions & QRegularExpression::CaseInsensitiveOption) + flags << QLatin1String("CaseInsensitiveOption"); + if (patternOptions & QRegularExpression::DotMatchesEverythingOption) + flags << QLatin1String("DotMatchesEverythingOption"); + if (patternOptions & QRegularExpression::MultilineOption) + flags << QLatin1String("MultilineOption"); + if (patternOptions & QRegularExpression::ExtendedPatternSyntaxOption) + flags << QLatin1String("ExtendedPatternSyntaxOption"); + if (patternOptions & QRegularExpression::InvertedGreedinessOption) + flags << QLatin1String("InvertedGreedinessOption"); + if (patternOptions & QRegularExpression::DontCaptureOption) + flags << QLatin1String("DontCaptureOption"); + if (patternOptions & QRegularExpression::UseUnicodePropertiesOption) + flags << QLatin1String("UseUnicodePropertiesOption"); + } + + debug.nospace() << "QRegularExpression::PatternOptions(" + << qPrintable(flags.join(QLatin1String("|"))) + << ")"; + + return debug.space(); +} /*! \relates QRegularExpressionMatch diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index c9bcb1e7ba..13c7de7cab 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -142,6 +142,7 @@ Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegularExpression &re); #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QRegularExpression &re); +Q_CORE_EXPORT QDebug operator<<(QDebug debug, QRegularExpression::PatternOptions patternOptions); #endif struct QRegularExpressionMatchPrivate; -- cgit v1.2.3 From bd30234b59c1a0cef81b8ce43f2fefac1f28b318 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 8 Feb 2012 18:53:22 +0000 Subject: QRegularExpression: improve operator==, add dedicated autotest Trivial change: compare dpointers first, then the data. Added test function for operator==. Change-Id: I33ac64a59db4ccad56c30be17622187e42415f38 Reviewed-by: Lars Knoll --- src/corelib/tools/qregularexpression.cpp | 3 +- .../qregularexpression/tst_qregularexpression.cpp | 64 ++++++++++++++++++++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 7fbbfaa9ef..b7a5c3de8e 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1395,7 +1395,8 @@ QRegularExpressionMatchIterator QRegularExpression::globalMatch(const QString &s */ bool QRegularExpression::operator==(const QRegularExpression &re) const { - return (pattern() == re.pattern() && patternOptions() == re.patternOptions()); + return (d == re.d) || + (d->pattern == re.d->pattern && d->patternOptions == re.d->patternOptions); } /*! diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 93cb6823cd..8365a09689 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -71,6 +71,8 @@ private slots: void globalMatch(); void serialize_data(); void serialize(); + void operatoreq_data(); + void operatoreq(); private: void provideRegularExpressions(); @@ -348,11 +350,6 @@ void tst_QRegularExpression::gettersSetters() QCOMPARE(re.pattern(), pattern); QCOMPARE(re.patternOptions(), patternOptions); } - { - QRegularExpression re(pattern, patternOptions); - QRegularExpression re2(pattern, patternOptions); - QVERIFY(re == re2); - } } void tst_QRegularExpression::escape_data() @@ -1144,6 +1141,63 @@ void tst_QRegularExpression::serialize() QCOMPARE(inRe, outRe); } +static void verifyEquality(const QRegularExpression &re1, const QRegularExpression &re2) +{ + QVERIFY(re1 == re2); + QVERIFY(re2 == re1); + QVERIFY(!(re1 != re2)); + QVERIFY(!(re2 != re1)); + + QRegularExpression re3(re1); + + QVERIFY(re1 == re3); + QVERIFY(re3 == re1); + QVERIFY(!(re1 != re3)); + QVERIFY(!(re3 != re1)); + + QVERIFY(re2 == re3); + QVERIFY(re3 == re2); + QVERIFY(!(re2 != re3)); + QVERIFY(!(re3 != re2)); + + re3 = re2; + QVERIFY(re1 == re3); + QVERIFY(re3 == re1); + QVERIFY(!(re1 != re3)); + QVERIFY(!(re3 != re1)); + + QVERIFY(re2 == re3); + QVERIFY(re3 == re2); + QVERIFY(!(re2 != re3)); + QVERIFY(!(re3 != re2)); +} + +void tst_QRegularExpression::operatoreq_data() +{ + provideRegularExpressions(); +} + +void tst_QRegularExpression::operatoreq() +{ + QFETCH(QString, pattern); + QFETCH(QRegularExpression::PatternOptions, patternOptions); + { + QRegularExpression re1(pattern); + QRegularExpression re2(pattern); + verifyEquality(re1, re2); + } + { + QRegularExpression re1(QString(), patternOptions); + QRegularExpression re2(QString(), patternOptions); + verifyEquality(re1, re2); + } + { + QRegularExpression re1(pattern, patternOptions); + QRegularExpression re2(pattern, patternOptions); + verifyEquality(re1, re2); + } +} + QTEST_APPLESS_MAIN(tst_QRegularExpression) #include "tst_qregularexpression.moc" -- cgit v1.2.3 From 1899861858eb262df7826eb32d1274233a35536e Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 8 Feb 2012 19:28:14 +0000 Subject: QRegularExpression: do not use JIT in debug builds PCRE's JIT uses self-modifying code extensively, requiring full SMC checks enabled by tools like valgrind, which slow down the execution considerably; not enabling SMC checks lead to crashes. Therefore, JIT is now disabled by default in debug builds of Qt. Its usage (both in debug and release builds) can be controlled by setting the QT_ENABLE_REGEXP_JIT environment variable. Change-Id: Ib38952400e4219582942ce65ab9edcd89c432f3e Reviewed-by: Lars Knoll --- src/corelib/tools/qregularexpression.cpp | 42 +++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index b7a5c3de8e..17988bdb31 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -509,6 +509,22 @@ QT_BEGIN_NAMESPACE QRegExp::CaretAtOffset behaviour. There is no equivalent for the other QRegExp::CaretMode modes. + \section1 Debugging code that uses QRegularExpression + + QRegularExpression internally uses a just in time compiler (JIT) to + optimize the execution of the matching algorithm. The JIT makes extensive + usage of self-modifying code, which can lead debugging tools such as + Valgrind to crash. You must enable all checks for self-modifying code if + you want to debug programs using QRegularExpression (f.i., see Valgrind's + \c{--smc-check} command line option). The downside of enabling such checks + is that your program will run considerably slower. + + To avoid that, the JIT is disabled by default if you compile Qt in debug + mode. It is possible to override the default and enable or disable the JIT + usage (both in debug or release mode) by setting the + \c{QT_ENABLE_REGEXP_JIT} environment variable to a non-zero or zero value + respectively. + \sa QRegularExpressionMatch, QRegularExpressionMatchIterator */ @@ -969,6 +985,25 @@ void QRegularExpressionPrivate::getPatternInfo() (patternNewlineSetting == PCRE_NEWLINE_ANYCRLF); } +/*! + \internal +*/ +static bool isJitEnabled() +{ + QByteArray jitEnvironment = qgetenv("QT_ENABLE_REGEXP_JIT"); + if (!jitEnvironment.isEmpty()) { + bool ok; + int enableJit = jitEnvironment.toInt(&ok); + return ok ? (enableJit != 0) : true; + } + +#ifdef QT_DEBUG + return false; +#else + return true; +#endif +} + /*! \internal */ @@ -981,7 +1016,12 @@ void QRegularExpressionPrivate::optimizePattern() if (studyData || (++usedCount != OPTIMIZE_AFTER_USE_COUNT)) return; - int studyOptions = PCRE_STUDY_JIT_COMPILE; + static const bool enableJit = isJitEnabled(); + + int studyOptions = 0; + if (enableJit) + studyOptions |= PCRE_STUDY_JIT_COMPILE; + const char *err; studyData = pcre16_study(compiledPattern, studyOptions, &err); -- cgit v1.2.3 From efcd4d9470781e3a0331afeab49cd00cee24399f Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sun, 19 Feb 2012 23:56:50 +0100 Subject: QRegularExpression: add captureCount() QRegularExpression::captureCount() returns the number of capturing groups inside the regular expression pattern. Change-Id: Ib90ce67c67d06ab2966f0c98bd91da21defc156d Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 13 +++++++++ src/corelib/tools/qregularexpression.h | 2 ++ .../qregularexpression/tst_qregularexpression.cpp | 31 ++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 17988bdb31..7bbac0144b 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1340,6 +1340,19 @@ void QRegularExpression::setPatternOptions(PatternOptions options) d->patternOptions = options; } +/*! + Returns the number of capturing groups inside the pattern string, + or -1 if the regular expression is not valid. + + \sa isValid() +*/ +int QRegularExpression::captureCount() const +{ + if (!isValid()) // will compile the pattern + return -1; + return d->capturingCount; +} + /*! Returns true if the regular expression is a valid regular expression (that is, it contains no syntax errors, etc.), or false otherwise. Use diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 13c7de7cab..3ca83c9e27 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -94,6 +94,8 @@ public: int patternErrorOffset() const; QString errorString() const; + int captureCount() const; + enum MatchType { NormalMatch = 0, PartialPreferCompleteMatch, diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 8365a09689..9430425532 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -73,6 +73,8 @@ private slots: void serialize(); void operatoreq_data(); void operatoreq(); + void captureCount_data(); + void captureCount(); private: void provideRegularExpressions(); @@ -1198,6 +1200,35 @@ void tst_QRegularExpression::operatoreq() } } +void tst_QRegularExpression::captureCount_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("captureCount"); + QTest::newRow("captureCount01") << "a pattern" << 0; + QTest::newRow("captureCount02") << "a.*pattern" << 0; + QTest::newRow("captureCount03") << "(a) pattern" << 1; + QTest::newRow("captureCount04") << "(a).*(pattern)" << 2; + QTest::newRow("captureCount05") << "^(?
\\w+) (?\\w+)$" << 2; + QTest::newRow("captureCount06") << "^(\\w+) (?\\w+) (.)$" << 3; + QTest::newRow("captureCount07") << "(?:non capturing) (capturing) (?named) (?:non (capturing))" << 3; + QTest::newRow("captureCount08") << "(?|(a)(b)|(c)(d))" << 2; + QTest::newRow("captureCount09") << "(?|(a)(b)|(c)(d)(?:e))" << 2; + QTest::newRow("captureCount10") << "(?|(a)(b)|(c)(d)(e)) (f)(g)" << 5; + QTest::newRow("captureCount11") << "(?|(a)(b)|(c)(d)(e)) (f)(?:g)" << 4; + QTest::newRow("captureCount_invalid01") << "(.*" << -1; + QTest::newRow("captureCount_invalid02") << "\\" << -1; + QTest::newRow("captureCount_invalid03") << "(? Date: Sun, 19 Feb 2012 23:58:04 +0100 Subject: QRegularExpression: const correctness fixes Adding some const qualifiers to members which are never written. Change-Id: Ibb8953764c7b7790a419a5d48f2956751d5fc1f9 Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 7bbac0144b..40b6b5a08e 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -817,14 +817,14 @@ struct QRegularExpressionMatchPrivate : QSharedData QRegularExpressionMatch nextMatch() const; - QRegularExpression regularExpression; - QString subject; + const QRegularExpression regularExpression; + const QString subject; // the capturedOffsets vector contains pairs of (start, end) positions // for each captured substring QVector capturedOffsets; - QRegularExpression::MatchType matchType; - QRegularExpression::MatchOptions matchOptions; + const QRegularExpression::MatchType matchType; + const QRegularExpression::MatchOptions matchOptions; int capturedCount; @@ -835,16 +835,16 @@ struct QRegularExpressionMatchPrivate : QSharedData struct QRegularExpressionMatchIteratorPrivate : QSharedData { - QRegularExpressionMatchIteratorPrivate(const QRegularExpression re, + QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, const QRegularExpressionMatch &next); bool hasNext() const; QRegularExpressionMatch next; - QRegularExpression regularExpression; - QRegularExpression::MatchType matchType; - QRegularExpression::MatchOptions matchOptions; + const QRegularExpression regularExpression; + const QRegularExpression::MatchType matchType; + const QRegularExpression::MatchOptions matchOptions; }; /*! @@ -1216,7 +1216,7 @@ QRegularExpressionMatch QRegularExpressionMatchPrivate::nextMatch() const /*! \internal */ -QRegularExpressionMatchIteratorPrivate::QRegularExpressionMatchIteratorPrivate(const QRegularExpression re, +QRegularExpressionMatchIteratorPrivate::QRegularExpressionMatchIteratorPrivate(const QRegularExpression &re, QRegularExpression::MatchType matchType, QRegularExpression::MatchOptions matchOptions, const QRegularExpressionMatch &next) -- cgit v1.2.3 From b979956ec46093e5668c2b264f9b68da3cbb0326 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 15 Feb 2012 09:56:23 +0100 Subject: QSqlTableModel: handle changes between submit and select Once an insert has been submitted, the cached record behaves like an update. For row bookkeeping, we still have to remember that it was originally inserted and is not in the query rows. Between submitting a delete and selecting, we remove the values from the deleted record. This causes a blank row to be displayed. Read-only flag is set for cells in deleted row. Reverting between submit and select means going back to the last submitted values. When removing rows, it's better to process from highest row numbers to lowest. This avoids complications with higher rows shifting down when lower rows are removed. Change-Id: I8752fa11f7a1b88f2a71b9e03a020ac37e62487f Reviewed-by: Honglei Zhang --- src/sql/models/qsqltablemodel.cpp | 52 +++++++++++++--------- src/sql/models/qsqltablemodel_p.h | 47 ++++++++++++++++--- .../models/qsqltablemodel/tst_qsqltablemodel.cpp | 8 ++-- 3 files changed, 75 insertions(+), 32 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 24668dd946..9ade5f14d5 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -87,7 +87,7 @@ int QSqlTableModelPrivate::insertCount(int maxRow) const for (; i != e && (maxRow < 0 || i.key() <= maxRow); ++i) { - if (i.value().op() == Insert) + if (i.value().insert()) ++cnt; } @@ -122,19 +122,17 @@ void QSqlTableModelPrivate::revertCachedRow(int row) Q_Q(QSqlTableModel); ModifiedRow r = cache.value(row); - // cannot revert a committed change - if (r.submitted()) - return; - switch (r.op()) { case QSqlTableModelPrivate::None: Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map"); return; case QSqlTableModelPrivate::Update: case QSqlTableModelPrivate::Delete: - cache.remove(row); - emit q->dataChanged(q->createIndex(row, 0), - q->createIndex(row, q->columnCount() - 1)); + if (!r.submitted()) { + cache[row].revert(); + emit q->dataChanged(q->createIndex(row, 0), + q->createIndex(row, q->columnCount() - 1)); + } break; case QSqlTableModelPrivate::Insert: { QMap::Iterator it = cache.find(row); @@ -373,7 +371,7 @@ bool QSqlTableModel::select() while (it != d->cache.constBegin()) { --it; // rows must be accounted for - if (it.value().op() == QSqlTableModelPrivate::Insert) { + if (it.value().insert()) { beginRemoveRows(QModelIndex(), it.key(), it.key()); it = d->cache.erase(it); endRemoveRows(); @@ -470,11 +468,14 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount()) return false; + if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete) + return false; + if (d->strategy == OnFieldChange && d->cache.value(index.row()).op() != QSqlTableModelPrivate::Insert) { - d->cache.clear(); + revertAll(); } else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(index.row())) { submit(); - d->cache.clear(); + revertAll(); } QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()]; @@ -759,8 +760,10 @@ void QSqlTableModel::revertAll() { Q_D(QSqlTableModel); - while (!d->cache.isEmpty()) - revertRow(d->cache.constBegin().key()); + const QList rows(d->cache.keys()); + for (int i = rows.size() - 1; i >= 0; --i) { + revertRow(rows.value(i)); + } } /*! @@ -967,15 +970,17 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) else if (!count) return true; - for (int i = 0; i < count; ++i) { - int idx = row + i; - if (d->cache.value(idx).op() == QSqlTableModelPrivate::Insert) { + // Iterate backwards so we don't have to worry about removed rows causing + // higher cache entries to shift downwards. + for (int idx = row + count - 1; idx >= row; --idx) { + QSqlTableModelPrivate::ModifiedRow& mrow = d->cache[idx]; + if (mrow.op() == QSqlTableModelPrivate::Insert) { revertRow(idx); - // Reverting a row means all the other cache entries have been adjusted downwards - // so fake this by adjusting row - --row; } else { - d->cache[idx] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx)); + if (mrow.op() == QSqlTableModelPrivate::None) + mrow = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Delete, record(idx)); + else + mrow.setOp(QSqlTableModelPrivate::Delete); if (d->strategy == OnManualSubmit) emit headerDataChanged(Qt::Vertical, idx, idx); } @@ -1158,6 +1163,8 @@ Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const return 0; if (d->rec.field(index.column()).isReadOnly()) return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + if (d->cache.value(index.row()).op() == QSqlTableModelPrivate::Delete) + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; } @@ -1186,8 +1193,11 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &values) if (row >= rowCount()) return false; + if (d->cache.value(row).op() == QSqlTableModelPrivate::Delete) + return false; + if (d->strategy == OnFieldChange && d->cache.value(row).op() != QSqlTableModelPrivate::Insert) - d->cache.clear(); + revertAll(); else if (d->strategy == OnRowChange && !d->cache.isEmpty() && !d->cache.contains(row)) submit(); diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index 57051a0e9c..ba2fdf5df3 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -101,18 +101,51 @@ public: { public: inline ModifiedRow(Op o = None, const QSqlRecord &r = QSqlRecord()) - : m_op(o), m_rec(r), m_submitted(false) - { init_rec(); } + : m_op(None), m_db_values(r), m_insert(o == Insert) + { setOp(o); } inline Op op() const { return m_op; } + inline void setOp(Op o) + { + if (o == m_op) + return; + m_submitted = (o != Insert && o != Delete); + m_op = o; + m_rec = m_db_values; + setGenerated(m_rec, m_op == Delete); + } inline QSqlRecord rec() const { return m_rec; } inline QSqlRecord& recRef() { return m_rec; } inline void setValue(int c, const QVariant &v) { + m_submitted = false; m_rec.setValue(c, v); m_rec.setGenerated(c, true); } inline bool submitted() const { return m_submitted; } - inline void setSubmitted() { m_submitted = true; } + inline void setSubmitted() + { + m_submitted = true; + setGenerated(m_rec, false); + if (m_op == Delete) { + m_rec.clearValues(); + } + else { + m_op = Update; + m_db_values = m_rec; + setGenerated(m_db_values, true); + } + } + inline bool insert() const { return m_insert; } + inline void revert() + { + if (m_submitted) + return; + if (m_op == Delete) + m_op = Update; + m_rec = m_db_values; + setGenerated(m_rec, false); + m_submitted = true; + } inline QSqlRecord primaryValues(const QSqlRecord& pi) const { if (m_op == None || m_op == Insert) @@ -126,16 +159,16 @@ public: return values; } private: - void init_rec() + inline static void setGenerated(QSqlRecord& r, bool g) { - for (int i = m_rec.count() - 1; i >= 0; --i) - m_rec.setGenerated(i, false); - m_db_values = m_rec; + for (int i = r.count() - 1; i >= 0; --i) + r.setGenerated(i, g); } Op m_op; QSqlRecord m_rec; QSqlRecord m_db_values; bool m_submitted; + bool m_insert; }; typedef QMap CacheMap; diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp index 270de8292b..43829987d4 100644 --- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp @@ -730,10 +730,10 @@ void tst_QSqlTableModel::removeRows() QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int))); QVERIFY(model.removeRows(0, 2, QModelIndex())); QCOMPARE(headerDataChangedSpy.count(), 2); - QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 0); - QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 0); - QCOMPARE(headerDataChangedSpy.at(1).at(1).toInt(), 1); - QCOMPARE(headerDataChangedSpy.at(1).at(2).toInt(), 1); + QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 1); + QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 1); + QCOMPARE(headerDataChangedSpy.at(1).at(1).toInt(), 0); + QCOMPARE(headerDataChangedSpy.at(1).at(2).toInt(), 0); QCOMPARE(model.rowCount(), 3); QVERIFY(beforeDeleteSpy.count() == 0); QVERIFY(model.submitAll()); -- cgit v1.2.3 From 291e2c7d5416af4d16dc0a6e60df7980ba745a3d Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Thu, 16 Feb 2012 02:38:02 +0100 Subject: QSqlTableModel: long live selectRow()! Change-Id: If26dbcc8a1e8ef1376ef7a688c946ce5270e5706 Reviewed-by: Yunqiao Yin --- src/sql/models/qsqltablemodel.cpp | 43 +++++++++++++++++++++++++++++++++++++++ src/sql/models/qsqltablemodel.h | 1 + src/sql/models/qsqltablemodel_p.h | 14 +++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 9ade5f14d5..40230c3043 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -391,6 +391,49 @@ bool QSqlTableModel::select() return true; } +/*! + Refreshes \a row in the model with values from the database table row matching + on primary key values. Without a primary key, all column values must match. If + no matching row is found, the model will show an empty row. + + Returns true if successful; otherwise returns false. + + \sa select() +*/ +bool QSqlTableModel::selectRow(int row) +{ + Q_D(QSqlTableModel); + + if (row < 0 || row >= rowCount()) + return false; + + const int table_sort_col = d->sortColumn; + d->sortColumn = -1; + const QString table_filter = d->filter; + d->filter = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, + d->tableName, + d->primaryValues(row), + false); + if (d->filter.startsWith(QLatin1String("WHERE "), Qt::CaseInsensitive)) + d->filter.remove(0, 6); + const QString stmt = selectStatement(); + d->sortColumn = table_sort_col; + d->filter = table_filter; + + QSqlQuery q(d->db); + q.setForwardOnly(true); + if (!q.exec(stmt)) + return false; + + bool exists = q.next(); + d->cache[row].refresh(exists, q.record()); + + emit headerDataChanged(Qt::Vertical, row, row); + emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); + + return true; +} + /*! \reimp */ diff --git a/src/sql/models/qsqltablemodel.h b/src/sql/models/qsqltablemodel.h index 38e92200c7..13316bc4ed 100644 --- a/src/sql/models/qsqltablemodel.h +++ b/src/sql/models/qsqltablemodel.h @@ -67,6 +67,7 @@ public: virtual ~QSqlTableModel(); virtual bool select(); + virtual bool selectRow(int row); virtual void setTable(const QString &tableName); QString tableName() const; diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index ba2fdf5df3..323964afe8 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -135,6 +135,20 @@ public: setGenerated(m_db_values, true); } } + inline void refresh(bool exists, const QSqlRecord& newvals) + { + m_submitted = true; + if (exists) { + m_op = Update; + m_db_values = newvals; + m_rec = newvals; + setGenerated(m_rec, false); + } else { + m_op = Delete; + m_rec.clear(); + m_db_values.clear(); + } + } inline bool insert() const { return m_insert; } inline void revert() { -- cgit v1.2.3 From 888fed8065f708baeb6efa5f280c2f1aec3dee78 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Tue, 21 Feb 2012 09:22:26 +0100 Subject: QSqlTableModel: use selectRow() for field and row edit strategies Calling select refreshes the query data but disrupts view navigation. For OnFieldChange and OnRecordChange it makes sense to only select the row in question. This does not disturb view navigation. Assume disruption of view navigation is not a problem for OnManualSubmit because the user or application decides when submitAll is called. Task-number: QTBUG-2875 Change-Id: I1e5f68668fb9102f6296d67d543e80daa403f1c4 Reviewed-by: Yunqiao Yin --- dist/changes-5.0.0 | 8 +++ src/sql/models/qsqltablemodel.cpp | 36 ++++++---- .../tst_qsqlrelationaltablemodel.cpp | 11 +++ .../models/qsqltablemodel/tst_qsqltablemodel.cpp | 79 ++++++++++++++++++---- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index dd0a0693ed..33a8869397 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -406,6 +406,14 @@ ignore the rest of the range. QSqlTableModel::indexInQuery() as example of how to implement in a subclass. +* QSqlTableModel edit strategies OnFieldChange/OnRowChange QTBUG-2875 +Previously, after changes were submitted in these edit strategies, select() +was called which removed and inserted all rows. This ruined navigation +in QTableView. Now, with these edit strategies, there is no implicit select() +done after committing. This includes deleted rows which remain in +the model as blank rows until the application calls select(). Instead, +selectRow() is called to refresh only the affected row. + **************************************************************************** * Database Drivers * **************************************************************************** diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 40230c3043..aa7dc3dcf8 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -663,8 +663,8 @@ bool QSqlTableModel::deleteRowFromTable(int row) Returns false on error, detailed error information can be obtained with lastError(). - On success the model will be repopulated. Any views - presenting it will lose their selections. + In OnManualSubmit, on success the model will be repopulated. + Any views presenting it will lose their selections. Note: In OnManualSubmit mode, already submitted changes won't be cleared from the cache when submitAll() fails. This allows @@ -677,6 +677,8 @@ bool QSqlTableModel::submitAll() { Q_D(QSqlTableModel); + bool success = true; + for (QSqlTableModelPrivate::CacheMap::Iterator it = d->cache.begin(); it != d->cache.constEnd(); ++it) { if (it.value().submitted()) @@ -684,25 +686,35 @@ bool QSqlTableModel::submitAll() switch (it.value().op()) { case QSqlTableModelPrivate::Insert: - if (!insertRowIntoTable(it.value().rec())) - return false; + success = insertRowIntoTable(it.value().rec()); break; case QSqlTableModelPrivate::Update: - if (!updateRowInTable(it.key(), it.value().rec())) - return false; + success = updateRowInTable(it.key(), it.value().rec()); break; case QSqlTableModelPrivate::Delete: - if (!deleteRowFromTable(it.key())) - return false; + success = deleteRowFromTable(it.key()); break; case QSqlTableModelPrivate::None: Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation"); break; } - it.value().setSubmitted(); + + if (success) { + it.value().setSubmitted(); + if (d->strategy != OnManualSubmit) + success = selectRow(it.key()); + } + + if (!success) + break; + } + + if (success) { + if (d->strategy == OnManualSubmit) + success = select(); } - return select(); + return success; } /*! @@ -719,8 +731,8 @@ bool QSqlTableModel::submitAll() Returns true on success; otherwise returns false. Use lastError() to query detailed error information. - On success the model will be repopulated. Any views - presenting it will lose their selections. + Does not automatically repopulate the model. Submitted rows are + refreshed from the database on success. \sa revert(), revertRow(), submitAll(), revertAll(), lastError() */ diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp index ddafeea427..ce0d8db1fd 100644 --- a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp +++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp @@ -542,6 +542,13 @@ void tst_QSqlRelationalTableModel::setRecord() model.setSort(0, Qt::AscendingOrder); QVERIFY_SQL(model, submit()); + if (model.editStrategy() != QSqlTableModel::OnManualSubmit) { + QCOMPARE(model.data(model.index(1, 0)).toInt(), 7); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("tester")); + QCOMPARE(model.data(model.index(1, 2)).toString(), QString("herr")); + QVERIFY_SQL(model, select()); + } + QCOMPARE(model.data(model.index(3, 0)).toInt(), 7); QCOMPARE(model.data(model.index(3, 1)).toString(), QString("tester")); QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr")); @@ -599,6 +606,8 @@ void tst_QSqlRelationalTableModel::insertWithStrategies() QVERIFY_SQL(model, submitAll()); model.setEditStrategy(QSqlTableModel::OnManualSubmit); + // The changes were submitted, but there was no automatic select to resort + QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0,0)).toInt(), 1); QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry")); @@ -1401,6 +1410,8 @@ void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers() QVERIFY_SQL(model, insertRecord(-1, rec)); model.submitAll(); + if (model.editStrategy() != QSqlTableModel::OnManualSubmit) + QVERIFY_SQL(model, select()); QCOMPARE(model.data(model.index(0, 0)).toInt(), 3); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Washington")); diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp index 43829987d4..448111cd9f 100644 --- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp @@ -411,8 +411,11 @@ void tst_QSqlTableModel::setRecord() } else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1) model.submit(); else { - // dataChanged() is not emitted when submitAll() is called - QCOMPARE(spy.count(), 1); + // dataChanged() emitted by selectRow() as well as setRecord() + if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnFieldChange) + QCOMPARE(spy.count(), 2); + else + QCOMPARE(spy.count(), 1); QCOMPARE(spy.at(0).count(), 2); QCOMPARE(qvariant_cast(spy.at(0).at(0)), model.index(i, 0)); QCOMPARE(qvariant_cast(spy.at(0).at(1)), model.index(i, rec.count() - 1)); @@ -471,8 +474,7 @@ void tst_QSqlTableModel::insertRow() rec.setValue(0, 42); rec.setValue(1, QString("francis")); - // FieldChange updates immediately and resorts - // Row/Manual submit does not resort + // Setting record does not cause resort QVERIFY(model.setRecord(2, rec)); QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); @@ -482,8 +484,23 @@ void tst_QSqlTableModel::insertRow() QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); - // See comment above setRecord - if (submitpolicy == QSqlTableModel::OnFieldChange) { + QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis")); + QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); + QCOMPARE(model.data(model.index(3, 0)).toInt(), 3); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); + + QVERIFY(model.submitAll()); + + if (submitpolicy == QSqlTableModel::OnManualSubmit) { + // After the submit we should have the resorted view + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); QCOMPARE(model.data(model.index(2, 0)).toInt(), 3); QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); QCOMPARE(model.data(model.index(2, 2)).toInt(), 3); @@ -491,6 +508,13 @@ void tst_QSqlTableModel::insertRow() QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); } else { + // Submit does not select, therefore not resorted + QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 2); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(1, 2)).toInt(), 2); QCOMPARE(model.data(model.index(2, 0)).toInt(), 42); QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis")); QCOMPARE(model.data(model.index(2, 2)).toInt(), 2); @@ -499,9 +523,8 @@ void tst_QSqlTableModel::insertRow() QCOMPARE(model.data(model.index(3, 2)).toInt(), 3); } - QVERIFY(model.submitAll()); - - // After the submit we should have the resorted view + QVERIFY(model.select()); + // After the select we should have the resorted view in all strategies QCOMPARE(model.data(model.index(0, 0)).toInt(), 1); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); QCOMPARE(model.data(model.index(0, 2)).toInt(), 1); @@ -514,7 +537,6 @@ void tst_QSqlTableModel::insertRow() QCOMPARE(model.data(model.index(3, 0)).toInt(), 42); QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis")); QCOMPARE(model.data(model.index(3, 2)).toInt(), 2); - } void tst_QSqlTableModel::insertRecord() @@ -647,8 +669,7 @@ void tst_QSqlTableModel::removeRow() QVERIFY_SQL(model, select()); QCOMPARE(model.rowCount(), 3); - // headerDataChanged must be emitted by the model when the edit strategy is OnManualSubmit, - // when OnFieldChange or OnRowChange it's not needed because the model will re-select. + // headerDataChanged must be emitted by the model since the row won't vanish until select qRegisterMetaType("Qt::Orientation"); QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int))); @@ -673,7 +694,10 @@ void tst_QSqlTableModel::removeRow() headerDataChangedSpy.clear(); QVERIFY(model.removeRow(1)); - QCOMPARE(headerDataChangedSpy.count(), 0); + QCOMPARE(headerDataChangedSpy.count(), 1); + QCOMPARE(model.rowCount(), 3); + + QVERIFY_SQL(model, select()); QCOMPARE(model.rowCount(), 2); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); @@ -706,6 +730,11 @@ void tst_QSqlTableModel::removeRows() QCOMPARE(beforeDeleteSpy.count(), 2); QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 0); QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 1); + // deleted rows shown as empty until select + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("")); + QVERIFY(model.select()); + // deleted rows are gone QCOMPARE(model.rowCount(), 1); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi")); model.clear(); @@ -778,6 +807,14 @@ void tst_QSqlTableModel::removeInsertedRow() model.submitAll(); + if (model.editStrategy() != QSqlTableModel::OnManualSubmit) { + QCOMPARE(model.rowCount(), 4); + QCOMPARE(model.data(model.index(1, 0)).toInt(), 55); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("null columns")); + QCOMPARE(model.data(model.index(1, 2)).isNull(), true); + QVERIFY(model.select()); + } + QCOMPARE(model.rowCount(), 4); QCOMPARE(model.data(model.index(3, 0)).toInt(), 55); QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns")); @@ -785,8 +822,17 @@ void tst_QSqlTableModel::removeInsertedRow() QVERIFY(model.removeRow(3)); model.submitAll(); - QCOMPARE(model.rowCount(), 3); + if (model.editStrategy() != QSqlTableModel::OnManualSubmit) { + QCOMPARE(model.rowCount(), 4); + QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); + QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); + QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); + QCOMPARE(model.data(model.index(3, 1)).toString(), QString("")); + QVERIFY(model.select()); + } + + QCOMPARE(model.rowCount(), 3); QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry")); QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond")); QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi")); @@ -1129,6 +1175,11 @@ void tst_QSqlTableModel::insertRecordBeforeSelect() buffer.setValue("title", 0); QVERIFY_SQL(model, insertRecord(1, buffer)); + if (model.editStrategy() != QSqlTableModel::OnManualSubmit) { + QCOMPARE(model.rowCount(), 2); + QVERIFY_SQL(model, select()); + } + int rowCount = model.rowCount(); model.clear(); QCOMPARE(model.rowCount(), 0); -- cgit v1.2.3 From ebb94587f69207d02269d7c20dd963e59629cfc4 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 2 Mar 2012 08:07:23 +0100 Subject: Use #define before including SHA-2 3rdparty code Using typedef causes errors due to re-definition, so #define the types needed by the SHA-2 code to the q[u]int* equivalents instead. Change-Id: I6fc29788dd05aeee28723820f511527d482d31f2 Reviewed-by: Oliver Wolff --- src/corelib/tools/qcryptographichash.cpp | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 3730a6c580..be124c94f7 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -48,23 +48,16 @@ #include "../../3rdparty/sha1/sha1.cpp" /* - These typedefs are needed by the RFC6234 code. Normally they would come - from from stdint.h, but since this header is not available on all platforms - (MSVC 2008, for example), we need to define them ourselves. + These #defines replace the typedefs needed by the RFC6234 code. Normally + the typedefs would come from from stdint.h, but since this header is not + available on all platforms (MSVC 2008, for example), we #define them to the + Qt equivalents. */ -#ifndef _UINT64_T_DECLARED -typedef QT_PREPEND_NAMESPACE(quint64) uint64_t; -#endif +#define uint64_t QT_PREPEND_NAMESPACE(quint64) +#define uint32_t QT_PREPEND_NAMESPACE(quint32) +#define uint8_t QT_PREPEND_NAMESPACE(quint8) +#define int_least16_t QT_PREPEND_NAMESPACE(qint16) -#ifndef _UINT32_T_DECLARED -typedef QT_PREPEND_NAMESPACE(quint32) uint32_t; -#endif - -#ifndef _UINT8_T_DECLARED -typedef QT_PREPEND_NAMESPACE(quint8) uint8_t; -#endif - -typedef QT_PREPEND_NAMESPACE(qint16) int_least16_t; // Header from rfc6234 with 1 modification: // sha1.h - commented out '#include ' on line 74 #include "../../3rdparty/rfc6234/sha.h" @@ -90,16 +83,21 @@ static int SHA384_512AddLength(SHA512Context *context, unsigned int length); // sha384-512.c - appended 'M' to the SHA224_256AddLength macro on line 304 #include "../../3rdparty/rfc6234/sha384-512.c" +#undef uint64_t +#undef uint32_t +#undef uint68_t +#undef int_least16_t + #include static inline int SHA224_256AddLength(SHA256Context *context, unsigned int length) { - uint32_t addTemp; + QT_PREPEND_NAMESPACE(quint32) addTemp; return SHA224_256AddLengthM(context, length); } static inline int SHA384_512AddLength(SHA512Context *context, unsigned int length) { - uint64_t addTemp; + QT_PREPEND_NAMESPACE(quint64) addTemp; return SHA384_512AddLengthM(context, length); } -- cgit v1.2.3 From c74bc26605f2337b13f366c2600fff4822d88ffe Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Tue, 6 Mar 2012 11:17:07 +1000 Subject: Support legacy QDataStream serialization of QDate. Commit 8327fa7c11f6c84ccc66be4365ee282a76288788 changed the type of the Julian day member of QDate from quint32 to qint64. This changed the QDataStream format. Keep the old behavior, with the limited date range, if the stream version is less than Qt_5_0. Change-Id: I800448979a1891581069f39de7f9ab9c634e4f0e Reviewed-by: John Layt Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 64ad3121d0..fa5eed4f86 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3511,7 +3511,10 @@ void QDateTime::detach() QDataStream &operator<<(QDataStream &out, const QDate &date) { - return out << (qint64)(date.jd); + if (out.version() < QDataStream::Qt_5_0) + return out << quint32(date.jd); + else + return out << qint64(date.jd); } /*! @@ -3524,9 +3527,16 @@ QDataStream &operator<<(QDataStream &out, const QDate &date) QDataStream &operator>>(QDataStream &in, QDate &date) { - qint64 jd; - in >> jd; - date.jd = jd; + if (in.version() < QDataStream::Qt_5_0) { + quint32 jd; + in >> jd; + date.jd = jd; + } else { + qint64 jd; + in >> jd; + date.jd = jd; + } + return in; } -- cgit v1.2.3 From 6b7898059386fe48d9de55d68f1f3f330ce8fb0a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 23 Feb 2012 02:49:52 +0000 Subject: QRegularExpression: fix autotest Some minor fixes: obviously, a valid match always come from a valid regular expression, but a valid regular expression can create an invalid match (internal error during matching). Also, testing an invalid iterator should silence the emitted warnings. Change-Id: I585bb99a81e22f108601fd66bf30b56e0229d68b Reviewed-by: Thiago Macieira --- .../auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 9430425532..238d8626c3 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -191,9 +191,8 @@ bool operator!=(const QList &expectedMatchList, const QRegularExpressionM void consistencyCheck(const QRegularExpressionMatch &match) { - QVERIFY(match.isValid() == match.regularExpression().isValid()); - if (match.isValid()) { + QVERIFY(match.regularExpression().isValid()); QVERIFY(!(match.hasMatch() && match.hasPartialMatch())); if (match.hasMatch() || match.hasPartialMatch()) { @@ -260,7 +259,9 @@ void consistencyCheck(const QRegularExpressionMatchIterator &iterator) } } else { QVERIFY(!i.hasNext()); + QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionMatchIterator::peekNext() called on an iterator already at end"); QRegularExpressionMatch peeked = i.peekNext(); + QTest::ignoreMessage(QtWarningMsg, "QRegularExpressionMatchIterator::next() called on an iterator already at end"); QRegularExpressionMatch match = i.next(); consistencyCheck(peeked); consistencyCheck(match); -- cgit v1.2.3 From 7ae6a6e744f92db2626b7c9b38175dc4140a4eaf Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 6 Mar 2012 17:55:14 +1000 Subject: Fixed warning from gcc with -Wundef for some values of WCHAR_MAX Certain versions of system headers will declare WCHAR_MAX like: #define __WCHAR_MAX ( (wchar_t) - 1 ) #define WCHAR_MAX __WCHAR_MAX In particular on ARM (see e.g. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=598937 ) In this case, defined(WCHAR_MAX) is true, but attempting to use the value of WCHAR_MAX in a preprocessor expression will not give the desired results - "wchar_t" is unknown to the preprocessor, so WCHAR_MAX silently (without -Wundef) evaluates to ( (0) - 1 ) == -1. A simple workaround is to avoid looking at WCHAR_MAX when the superior __SIZEOF_WCHAR_T__ is defined. Change-Id: I439b166cffb93416737ee19025fb6e8d51c27876 Reviewed-by: Bradley T. Hughes Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 6fc86fc04b..4d02fbe66d 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -98,7 +98,9 @@ template struct QConstStringData #define QT_UNICODE_LITERAL_II(str) u"" str -#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) +#elif defined(Q_OS_WIN) \ + || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) \ + || (!defined(__SIZEOF_WCHAR_T__) && defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536)) // wchar_t is 2 bytes template struct QConstStringData { -- cgit v1.2.3 From 53bbea232830af3f056cd8253c4ff4dd33f525c7 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 6 Mar 2012 13:05:09 +0100 Subject: Fix parsing of unicode escape sequences Change-Id: I63a7cd3a571fb47c97157bcb2ca29c4239c600ba Reviewed-by: Thiago Macieira --- src/corelib/json/qjsonparser.cpp | 4 ++-- tests/auto/corelib/json/test.bjson | Bin 60992 -> 60992 bytes tests/auto/corelib/json/tst_qtjson.cpp | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp index 16eedadf1a..a83685da22 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/json/qjsonparser.cpp @@ -584,9 +584,9 @@ static inline bool addHexDigit(char digit, uint *result) if (digit >= '0' && digit <= '9') *result |= (digit - '0'); else if (digit >= 'a' && digit <= 'f') - *result |= (digit - 'a'); + *result |= (digit - 'a') + 10; else if (digit >= 'A' && digit <= 'F') - *result |= (digit - 'A'); + *result |= (digit - 'A') + 10; else return false; return true; diff --git a/tests/auto/corelib/json/test.bjson b/tests/auto/corelib/json/test.bjson index aa412eec67..9a0515f3ef 100644 Binary files a/tests/auto/corelib/json/test.bjson and b/tests/auto/corelib/json/test.bjson differ diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index f5b4f17732..f35831c900 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -115,6 +115,8 @@ private Q_SLOTS: void testCompaction(); void testDebugStream(); void testCompactionError(); + + void parseUnicodeEscapes(); private: QString testDataDir; }; @@ -1758,5 +1760,19 @@ void TestQtJson::testCompactionError() } } +void TestQtJson::parseUnicodeEscapes() +{ + const QByteArray json = "[ \"A\\u00e4\\u00C4\" ]"; + + QJsonDocument doc = QJsonDocument::fromJson(json); + QJsonArray array = doc.array(); + + QString result = QLatin1String("A"); + result += QChar(0xe4); + result += QChar(0xc4); + + QCOMPARE(array.first().toString(), result); +} + QTEST_MAIN(TestQtJson) #include "tst_qtjson.moc" -- cgit v1.2.3 From 1c438f104815e670afd94bfb396922dae09e7dcd Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 5 Mar 2012 16:56:55 +0100 Subject: Fix off by one in updateAccessibility. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that indexOfChild is 0-based, the update notifications should follow. Change-Id: I5e0303516d503d5e23061df5894b2428c00da2ce Reviewed-by: Jan-Arve Sæther Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/windows/qwindowsaccessibility.cpp | 14 ++++++-------- src/widgets/widgets/qmenu.cpp | 2 +- src/widgets/widgets/qmenubar.cpp | 1 - src/widgets/widgets/qtabbar.cpp | 4 ++-- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp index 1a8f593609..134b1c81ce 100644 --- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp @@ -844,14 +844,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I QPair ref = qAccessibleRecentSentEvents()->value(entry); if (ref.first) { acc = QAccessible::queryAccessibleInterface(ref.first); - if (acc && ref.second) { - if (ref.second) { - QAccessibleInterface *res = acc->child(ref.second - 1); - delete acc; - if (!res) - return E_INVALIDARG; - acc = res; - } + if (acc && ref.second >= 0) { + QAccessibleInterface *res = acc->child(ref.second); + delete acc; + if (!res) + return E_INVALIDARG; + acc = res; } } } else { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 3fb2a6122c..fd030a5383 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -1075,7 +1075,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e if (action_e == QAction::Hover) { #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { - int actionIndex = indexOf(action) + 1; + int actionIndex = indexOf(action); QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, q, actionIndex)); QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, q, actionIndex)); } diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 11f6592cc9..0efa6caebc 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -531,7 +531,6 @@ void QMenuBarPrivate::_q_actionHovered() #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { int actionIndex = actions.indexOf(action); - ++actionIndex; QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, q, actionIndex)); QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, q, actionIndex)); } diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index ca94854d11..ce25a22847 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -1183,8 +1183,8 @@ void QTabBar::setCurrentIndex(int index) d->layoutTab(index); #ifndef QT_NO_ACCESSIBILITY if (QAccessible::isActive()) { - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, index + 1)); - QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, this, index + 1)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Focus, this, index)); + QAccessible::updateAccessibility(QAccessibleEvent(QAccessible::Selection, this, index)); } #endif emit currentChanged(index); -- cgit v1.2.3 From 76d0df1b0ad9de56b7ca2e86c254f61d6e5ea702 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Tue, 6 Mar 2012 17:50:05 +1000 Subject: Fixed warnings from arm builds with -Wundef Do not use the value of a macro before verifying that the macro is defined. Change-Id: I36bebe37da5f4e5e7af1e423b7f2b18091e35707 Reviewed-by: Oswald Buddenhagen Reviewed-by: Bradley T. Hughes --- src/corelib/global/qprocessordetection.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 4213d5830e..1f16f090a9 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -93,7 +93,7 @@ || defined(__ARM_ARCH_7A__) \ || defined(__ARM_ARCH_7R__) \ || defined(__ARM_ARCH_7M__) \ - || (__TARGET_ARCH_ARM-0 >= 7) + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) # define Q_PROCESSOR_ARM_V7 # define Q_PROCESSOR_ARM_V6 # define Q_PROCESSOR_ARM_V5 @@ -104,11 +104,11 @@ || defined(__ARM_ARCH_6K__) \ || defined(__ARM_ARCH_6ZK__) \ || defined(__ARM_ARCH_6M__) \ - || (__TARGET_ARCH_ARM-0 >= 6) + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) # define Q_PROCESSOR_ARM_V6 # define Q_PROCESSOR_ARM_V5 # elif defined(__ARM_ARCH_5TEJ__) \ - || (__TARGET_ARCH_ARM-0 >= 5) + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) # define Q_PROCESSOR_ARM_V5 # endif # if defined(__ARMEL__) -- cgit v1.2.3 From 02d947524d887e3ff6cb24065ccdbf3311ea81a8 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 3 Mar 2012 12:41:13 +0000 Subject: QRegularExpression: fix documentation due to qdoc changes Removes the usage of various qdoc macros which are now deprecated. Change-Id: I74fa70f8d2a2a1bff57cdb2bcc14a31a7198dea0 Reviewed-by: Casper van Donderen --- src/corelib/tools/qregularexpression.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 40b6b5a08e..7faa907e35 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -73,21 +73,21 @@ QT_BEGIN_NAMESPACE strings and texts. This is useful in many contexts, e.g., \table - \row \i Validation - \i A regexp can test whether a substring meets some criteria, + \row \li Validation + \li A regexp can test whether a substring meets some criteria, e.g. is an integer or contains no whitespace. - \row \i Searching - \i A regexp provides more powerful pattern matching than + \row \li Searching + \li A regexp provides more powerful pattern matching than simple substring matching, e.g., match one of the words \e{mail}, \e{letter} or \e{correspondence}, but none of the words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc. - \row \i Search and Replace - \i A regexp can replace all occurrences of a substring with a + \row \li Search and Replace + \li A regexp can replace all occurrences of a substring with a different substring, e.g., replace all occurrences of \e{&} with \e{\&} except where the \e{&} is already followed by an \e{amp;}. - \row \i String Splitting - \i A regexp can be used to identify where a string should be + \row \li String Splitting + \li A regexp can be used to identify where a string should be split apart, e.g. splitting tab-delimited strings. \endtable @@ -99,12 +99,12 @@ QT_BEGIN_NAMESPACE Good references about regular expressions include: \list - \o \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. + \li \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4; - \o the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing + \li the \l{http://pcre.org/pcre.txt} {pcrepattern(3)} man page, describing the pattern syntax supported by PCRE (the reference implementation of Perl-compatible regular expressions); - \o the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression + \li the \l{http://perldoc.perl.org/perlre.html} {Perl's regular expression documentation} and the \l{http://perldoc.perl.org/perlretut.html} {Perl's regular expression tutorial}. \endlist @@ -117,7 +117,7 @@ QT_BEGIN_NAMESPACE supports Unicode. For an overview of the regular expression syntax supported by QRegularExpression, please refer to the aforementioned pcrepattern(3) man page. A regular expression is made up of two things: a - \bold{pattern string} and a set of \bold{pattern options} that change the + \b{pattern string} and a set of \b{pattern options} that change the meaning of the pattern string. You can set the pattern string by passing a string to the QRegularExpression @@ -307,9 +307,9 @@ QT_BEGIN_NAMESPACE to do so we must distinguish three cases: \list - \o the input cannot possibly match the regular expression; - \o the input does match the regular expression; - \o the input does not match the regular expression right now, + \li the input cannot possibly match the regular expression; + \li the input does match the regular expression; + \li the input does not match the regular expression right now, but it will if more charaters will be added to it. \endlist @@ -653,7 +653,7 @@ QT_BEGIN_NAMESPACE \value ExtendedPatternSyntaxOption Any whitespace in the pattern string which is not escaped and outside a - character class is ignored. Moreover, an unescaped sharp (\bold{#}) + character class is ignored. Moreover, an unescaped sharp (\b{#}) outside a character class causes all the following characters, until the first newline (included), to be ignored. This can be used to increase the readability of a pattern string as well as put comments -- cgit v1.2.3 From eddabd2395c6bf6516893d04c22e7fde2be9e1a1 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 6 Mar 2012 16:29:50 +0100 Subject: Fix the bit test for ABS_MT_SLOT to detect protocol B I tested, it didn't work. This is from a previous patch I had already gotten working before 40a5ba4d3fccb449dcfd8d9a0deaf4c7f0fe12bc was submitted. Change-Id: I868f069fe834b3122ed9b5b3dc9af0781d6e1d0d Reviewed-by: Laszlo Agocs --- src/plugins/generic/evdevtouch/qevdevtouch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp index 73f253ae96..9e6347457d 100644 --- a/src/plugins/generic/evdevtouch/qevdevtouch.cpp +++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp @@ -134,7 +134,7 @@ void QTouchScreenData::registerDevice() static inline bool testBit(long bit, const long *array) { - return array[bit / LONG_BITS] & (1 << (bit & (LONG_BITS - 1))); + return (array[bit / LONG_BITS] >> bit % LONG_BITS) & 1; } QTouchScreenHandler::QTouchScreenHandler(const QString &spec) -- cgit v1.2.3 From b371f3f943703840d0dfbe30505018bcca06e260 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 6 Mar 2012 16:09:09 +0200 Subject: Fix double click handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now double clicking in Qt 5 resulted in the following sequence of mouse events: pressed, released, double clicked, released. This is wrong, the press belonging to the second button down is missing. In Qt 4 that pressed event is present. The problem is not apparent in desktop environments because the double click is functioning properly even when the second pressed is missing. However when using a platform plug-in like wayland, where the clients receive only press, move and release events, double click was broken because the second click was effectively ignored (due to receiving nothing but a button release). Change-Id: Ief6af12c666b23e544da4a68cb835cd577265469 Reviewed-by: Samuel Rødal --- src/gui/kernel/qguiapplication.cpp | 42 +++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index be82005a54..095336a948 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -933,6 +933,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QPointF globalPoint = e->globalPos; Qt::MouseButton button = Qt::NoButton; + bool doubleClick = false; if (QGuiApplicationPrivate::lastCursorPosition != globalPoint) { type = QEvent::MouseMove; @@ -940,8 +941,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance|| qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance) mousePressButton = Qt::NoButton; - } - else { // Check to see if a new button has been pressed/released. + } else { // Check to see if a new button has been pressed/released. for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) { @@ -956,25 +956,19 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo } buttons = e->buttons; if (button & e->buttons) { - if ((e->timestamp - mousePressTime) < static_cast(qApp->styleHints()->mouseDoubleClickInterval()) && - button == mousePressButton) { - type = QEvent::MouseButtonDblClick; - mousePressButton = Qt::NoButton; - } - else { - type = QEvent::MouseButtonPress; - mousePressTime = e->timestamp; - mousePressButton = button; - const QPoint point = QGuiApplicationPrivate::lastCursorPosition.toPoint(); - mousePressX = point.x(); - mousePressY = point.y(); - } - } - else + ulong doubleClickInterval = static_cast(qApp->styleHints()->mouseDoubleClickInterval()); + doubleClick = e->timestamp - mousePressTime < doubleClickInterval && button == mousePressButton; + type = QEvent::MouseButtonPress; + mousePressTime = e->timestamp; + mousePressButton = button; + const QPoint point = QGuiApplicationPrivate::lastCursorPosition.toPoint(); + mousePressX = point.x(); + mousePressY = point.y(); + } else { type = QEvent::MouseButtonRelease; + } } - if (window) { QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); ev.setTimestamp(e->timestamp); @@ -1017,12 +1011,16 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo fake.synthetic = true; processTouchEvent(&fake); } + if (doubleClick) { + mousePressButton = Qt::NoButton; + QMouseEvent dblClickEvent(QEvent::MouseButtonDblClick, localPoint, localPoint, globalPoint, + button, buttons, e->modifiers); + dblClickEvent.setTimestamp(e->timestamp); + QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent); + } } } - -//### there's a lot of duplicated logic here -- refactoring required! - void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e) { if (!e->window) @@ -1041,8 +1039,6 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh } } - - // Remember, Qt convention is: keyboard state is state *before* void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e) -- cgit v1.2.3 From 484e2923b45ceccb0ea547a4a860ecc5315ada67 Mon Sep 17 00:00:00 2001 From: Donald Carr Date: Fri, 2 Mar 2012 04:58:33 +0000 Subject: Query udev build parameters from pkg-config Change-Id: Ia3b7329d7359684ee7bf572a7e5fb681105108f4 Reviewed-by: Donald Carr Reviewed-by: Holger Freyther Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- config.tests/unix/libudev/libudev.pro | 3 ++- configure | 9 ++++++++- mkspecs/common/linux.conf | 1 + src/platformsupport/udev/udev.pri | 2 ++ src/plugins/generic/evdevkeyboard/evdevkeyboard.pro | 4 ++-- src/plugins/generic/evdevmouse/evdevmouse.pro | 2 ++ src/plugins/generic/evdevtouch/evdevtouch.pro | 2 ++ 7 files changed, 19 insertions(+), 4 deletions(-) diff --git a/config.tests/unix/libudev/libudev.pro b/config.tests/unix/libudev/libudev.pro index 7f571b5a6d..28b8980e2e 100644 --- a/config.tests/unix/libudev/libudev.pro +++ b/config.tests/unix/libudev/libudev.pro @@ -1,3 +1,4 @@ SOURCES = libudev.cpp CONFIG -= qt -LIBS += -ludev +LIBS += $$QMAKE_LIBS_LIBUDEV +INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV diff --git a/configure b/configure index 90e0a5fcda..f29df99ae9 100755 --- a/configure +++ b/configure @@ -5294,7 +5294,13 @@ if [ "$PLATFORM_QPA" = "yes" ]; then fi if [ "$CFG_LIBUDEV" != "no" ]; then - if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/libudev "libudev" $L_FLAGS $I_FLAGS $l_FLAGS; then + if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists libudev 2>/dev/null; then + QMAKE_INCDIR_LIBUDEV=`$PKG_CONFIG --cflags-only-I libudev 2>/dev/null | sed -e 's,^-I,,g' -e 's, -I, ,g'` + QMAKE_LIBS_LIBUDEV=`$PKG_CONFIG --libs libudev 2>/dev/null` + QMakeVar set QMAKE_INCDIR_LIBUDEV "$QMAKE_INCDIR_LIBUDEV" + QMakeVar set QMAKE_LIBS_LIBUDEV "$QMAKE_LIBS_LIBUDEV" + fi + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/libudev "libudev" $L_FLAGS $I_FLAGS $l_FLAGS $QMAKE_INCDIR_LIBUDEV $QMAKE_LIBS_LIBUDEV; then CFG_LIBUDEV=yes QT_CONFIG="$QT_CONFIG libudev" elif [ "$CFG_LIBUDEV" = "yes" ]; then @@ -6890,6 +6896,7 @@ else fi echo "zlib support ........... $CFG_ZLIB" echo "Session management ..... $CFG_SM" +echo "libudev support ........ $CFG_LIBUDEV" if [ "$CFG_OPENGL" = "desktop" ]; then echo "OpenGL support ......... yes (Desktop OpenGL)" diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index a809a6b6f9..384c013309 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -34,6 +34,7 @@ QMAKE_LIBS_OPENGL_ES1 = -lGLES_CM QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 QMAKE_LIBS_OPENVG = -lOpenVG QMAKE_LIBS_THREAD = -lpthread +QMAKE_LIBS_LIBUDEV = -ludev QMAKE_CFLAGS_WAYLAND = QMAKE_INCDIR_WAYLAND = diff --git a/src/platformsupport/udev/udev.pri b/src/platformsupport/udev/udev.pri index 21c71d5f5b..c99d4b6810 100644 --- a/src/platformsupport/udev/udev.pri +++ b/src/platformsupport/udev/udev.pri @@ -1,4 +1,6 @@ contains(QT_CONFIG, libudev) { HEADERS += $$PWD/qudevhelper_p.h $$PWD/qudevicehelper_p.h SOURCES += $$PWD/qudevhelper.cpp $$PWD/qudevicehelper.cpp + + INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV } diff --git a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro index 82edf170a8..21e4bf63ee 100644 --- a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro +++ b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro @@ -12,11 +12,11 @@ HEADERS = \ QT += core-private platformsupport-private -LIBS += -ludev - SOURCES = main.cpp \ qevdevkeyboardhandler.cpp \ qevdevkeyboardmanager.cpp OTHER_FILES += \ evdevkeyboard.json + +LIBS += $$QMAKE_LIBS_LIBUDEV diff --git a/src/plugins/generic/evdevmouse/evdevmouse.pro b/src/plugins/generic/evdevmouse/evdevmouse.pro index c5d162fb2f..781d901f28 100644 --- a/src/plugins/generic/evdevmouse/evdevmouse.pro +++ b/src/plugins/generic/evdevmouse/evdevmouse.pro @@ -14,3 +14,5 @@ SOURCES = main.cpp \ OTHER_FILES += \ evdevmouse.json + +LIBS += $$QMAKE_LIBS_LIBUDEV diff --git a/src/plugins/generic/evdevtouch/evdevtouch.pro b/src/plugins/generic/evdevtouch/evdevtouch.pro index f9fb4a61d8..192a87c2a3 100644 --- a/src/plugins/generic/evdevtouch/evdevtouch.pro +++ b/src/plugins/generic/evdevtouch/evdevtouch.pro @@ -16,6 +16,8 @@ QT += core-private platformsupport-private OTHER_FILES += \ evdevtouch.json +LIBS += $$QMAKE_LIBS_LIBUDEV + # DEFINES += USE_MTDEV contains(DEFINES, USE_MTDEV): LIBS += -lmtdev -- cgit v1.2.3 From 393356f5f622eb6a491e4c82b517e8d6c5d93a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 6 Mar 2012 12:04:37 +0100 Subject: Add benchmark for QMetaType::create(). A case of a custom type creation was not covered before. Change-Id: Icd2a7d63633f8e40d9d4a8a26e0eb0896fc85ec8 Reviewed-by: Kent Hansen --- .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp index a3cdd38e56..c80a946366 100644 --- a/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/benchmarks/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -77,6 +77,9 @@ private slots: void constructCoreTypeCopy_data(); void constructCoreTypeCopy(); + void constructCustomType_data(); + void constructCustomType(); + void constructInPlace_data(); void constructInPlace(); void constructInPlaceCopy_data(); @@ -309,6 +312,24 @@ void tst_QMetaType::constructCoreTypeCopy() } } +void tst_QMetaType::constructCustomType_data() +{ + QTest::addColumn("typeId"); + + QTest::newRow("BigClass") << qMetaTypeId(); +} + +void tst_QMetaType::constructCustomType() +{ + QFETCH(int, typeId); + QBENCHMARK { + for (int i = 0; i < 100000; ++i) { + void *data = QMetaType::create(typeId, (void *)0); + QMetaType::destroy(typeId, data); + } + } +} + void tst_QMetaType::constructInPlace_data() { constructCoreType_data(); -- cgit v1.2.3 From 6e58dd34ac96e2cf0807a227caaef74d15e272e7 Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Tue, 6 Mar 2012 15:21:19 +0100 Subject: Renaming QNX mkspecs Renamed from blackberry-* to qnx-* in order to match he - pattern. Change-Id: I378151f3d564dd280943c74865a1d2b97215b656 Reviewed-by: Oswald Buddenhagen --- .../unsupported/blackberry-armv7le-qcc/qmake.conf | 25 ----- .../blackberry-armv7le-qcc/qplatformdefs.h | 102 -------------------- mkspecs/unsupported/blackberry-x86-qcc/qmake.conf | 25 ----- .../unsupported/blackberry-x86-qcc/qplatformdefs.h | 102 -------------------- mkspecs/unsupported/qnx-X11-g++/qmake.conf | 58 +++++++++++ mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h | 106 +++++++++++++++++++++ mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf | 25 +++++ .../unsupported/qnx-armv7le-qcc/qplatformdefs.h | 102 ++++++++++++++++++++ mkspecs/unsupported/qnx-g++/qmake.conf | 58 ----------- mkspecs/unsupported/qnx-g++/qplatformdefs.h | 106 --------------------- mkspecs/unsupported/qnx-x86-qcc/qmake.conf | 25 +++++ mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h | 102 ++++++++++++++++++++ 12 files changed, 418 insertions(+), 418 deletions(-) delete mode 100644 mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf delete mode 100644 mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h delete mode 100644 mkspecs/unsupported/blackberry-x86-qcc/qmake.conf delete mode 100644 mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h create mode 100644 mkspecs/unsupported/qnx-X11-g++/qmake.conf create mode 100644 mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h create mode 100644 mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf create mode 100644 mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h delete mode 100644 mkspecs/unsupported/qnx-g++/qmake.conf delete mode 100644 mkspecs/unsupported/qnx-g++/qplatformdefs.h create mode 100644 mkspecs/unsupported/qnx-x86-qcc/qmake.conf create mode 100644 mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h diff --git a/mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf b/mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf deleted file mode 100644 index f2407a6c13..0000000000 --- a/mkspecs/unsupported/blackberry-armv7le-qcc/qmake.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# qmake configuration for blackberry-qcc -# - -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl qnx -QT += core gui - -include(../../common/g++-unix.conf) -include(../../common/unix.conf) - -QMAKE_CC = qcc -Vgcc_ntoarmv7le -QNX_CPUDIR = armle-v7 - -include(../../common/qcc-base-qnx.conf) - -QMAKE_AR = ntoarmv7-ar cqs -QMAKE_OBJCOPY = ntoarmv7-objcopy -QMAKE_RANLIB = ntoarmv7-ranlib - -QMAKE_STRIP = ntoarmv7-strip - -load(qt_config) diff --git a/mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h b/mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h deleted file mode 100644 index 8ef80c4bd7..0000000000 --- a/mkspecs/unsupported/blackberry-armv7le-qcc/qplatformdefs.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Research In Motion Limited. -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H - -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - -#define __STDC_CONSTANT_MACROS - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -// QNX doesn't have the System V header. This is not a standard -// POSIX header, it's only documented in the Single UNIX Specification. -// The preferred POSIX compliant way to share memory is to use the functions -// in that comply with the POSIX Real Time Interface (1003.1b). -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -// for htonl -#include - -#define QT_USE_XOPEN_LFS_EXTENSIONS -#define QT_NO_READDIR64 -#include "../../common/posix/qplatformdefs.h" - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf - -// QNX6 doesn't have getpagesize() -inline int getpagesize() -{ - return ::sysconf(_SC_PAGESIZE); -} - -#include - -#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) - -#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/blackberry-x86-qcc/qmake.conf b/mkspecs/unsupported/blackberry-x86-qcc/qmake.conf deleted file mode 100644 index 93f1df2e07..0000000000 --- a/mkspecs/unsupported/blackberry-x86-qcc/qmake.conf +++ /dev/null @@ -1,25 +0,0 @@ -# -# qmake configuration for blackberry-qcc -# - -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui - -include(../../common/g++-unix.conf) -include(../../common/unix.conf) - -QMAKE_CC = qcc -Vgcc_ntox86 -QNX_CPUDIR = x86 - -include(../../common/qcc-base-qnx.conf) - -QMAKE_AR = ntox86-ar cqs -QMAKE_OBJCOPY = ntox86-objcopy -QMAKE_RANLIB = ntox86-ranlib - -QMAKE_STRIP = ntox86-strip - -load(qt_config) diff --git a/mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h b/mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h deleted file mode 100644 index 8ef80c4bd7..0000000000 --- a/mkspecs/unsupported/blackberry-x86-qcc/qplatformdefs.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Research In Motion Limited. -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H - -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - -#define __STDC_CONSTANT_MACROS - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -// QNX doesn't have the System V header. This is not a standard -// POSIX header, it's only documented in the Single UNIX Specification. -// The preferred POSIX compliant way to share memory is to use the functions -// in that comply with the POSIX Real Time Interface (1003.1b). -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -// for htonl -#include - -#define QT_USE_XOPEN_LFS_EXTENSIONS -#define QT_NO_READDIR64 -#include "../../common/posix/qplatformdefs.h" - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf - -// QNX6 doesn't have getpagesize() -inline int getpagesize() -{ - return ::sysconf(_SC_PAGESIZE); -} - -#include - -#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) - -#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/qnx-X11-g++/qmake.conf b/mkspecs/unsupported/qnx-X11-g++/qmake.conf new file mode 100644 index 0000000000..94f207aff6 --- /dev/null +++ b/mkspecs/unsupported/qnx-X11-g++/qmake.conf @@ -0,0 +1,58 @@ +# +# qmake configuration for qnx-x11-g++ +# +# Written for QNX RTOS v6 with X11 +# + +MAKEFILE_GENERATOR = UNIX +TARGET_PLATFORM = unix +TEMPLATE = app +CONFIG += qt warn_on release link_prl +QT += core gui + +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) +include(../common/unix.conf) + +QMAKE_CFLAGS_THREAD = -D_REENTRANT +QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD +QMAKE_COMPILER_DEFINES += __QNXNTO__ + +QMAKE_INCDIR = +QMAKE_LIBDIR = +QMAKE_INCDIR_X11 = /opt/X11R6/include +QMAKE_LIBDIR_X11 = /opt/X11R6/lib +QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] +QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] +QMAKE_INCDIR_OPENGL = /opt/X11R6/include +QMAKE_LIBDIR_OPENGL = /opt/X11R6/lib + +#QMAKE_LIBS = -lunix +QMAKE_LIBS = +QMAKE_LIBS_DYNLOAD = +QMAKE_LIBS_X11 = -lXext -lX11 -lm -lsocket +QMAKE_LIBS_X11SM = -lSM -lICE +QMAKE_LIBS_OPENGL = -lGL +QMAKE_LIBS_OPENGL_QT = -lGL +QMAKE_LIBS_THREAD = +QMAKE_LIBS_NETWORK = -lsocket + +QMAKE_AR = ar cqs +QMAKE_RANLIB = + +QMAKE_TAR = tar -cf +QMAKE_GZIP = gzip -9f + +QMAKE_COPY = cp -f +QMAKE_COPY_FILE = $(COPY) +QMAKE_COPY_DIR = $(COPY) -r +QMAKE_MOVE = mv -f +QMAKE_DEL_FILE = rm -f +QMAKE_DEL_DIR = rmdir +QMAKE_CHK_DIR_EXISTS = test -d +QMAKE_MKDIR = mkdir -p +QMAKE_STRIP = strip +QMAKE_STRIPFLAGS_LIB += --strip-unneeded +QMAKE_CHK_DIR_EXISTS = test -d +QMAKE_MKDIR = mkdir -p +load(qt_config) diff --git a/mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h b/mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h new file mode 100644 index 0000000000..489e1be114 --- /dev/null +++ b/mkspecs/unsupported/qnx-X11-g++/qplatformdefs.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +#include + + +// We are hot - unistd.h should have turned on the specific APIs we requested + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// QNX doesn't have the System V header. This is not a standard +// POSIX header, it's only documented in the Single UNIX Specification. +// The preferred POSIX compliant way to share memory is to use the functions +// in that comply with the POSIX Real Time Interface (1003.1b). +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +// for htonl +#include + +#define QT_USE_XOPEN_LFS_EXTENSIONS +#include "../../common/posix/qplatformdefs.h" + +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf + +// QNX6 doesn't have getpagesize() +inline int getpagesize() +{ + return ::sysconf(_SC_PAGESIZE); +} + +#include + +// QNX6 doesn't have strtof - use strtod instead +inline float strtof(const char *b, char **e) +{ + return float(strtod(b, e)); +} + +#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf b/mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf new file mode 100644 index 0000000000..ea206e28ec --- /dev/null +++ b/mkspecs/unsupported/qnx-armv7le-qcc/qmake.conf @@ -0,0 +1,25 @@ +# +# qmake configuration for qnx-qcc armv7 targets +# + +MAKEFILE_GENERATOR = UNIX +TARGET_PLATFORM = unix +TEMPLATE = app +CONFIG += qt warn_on release link_prl qnx +QT += core gui + +include(../../common/g++-unix.conf) +include(../../common/unix.conf) + +QMAKE_CC = qcc -Vgcc_ntoarmv7le +QNX_CPUDIR = armle-v7 + +include(../../common/qcc-base-qnx.conf) + +QMAKE_AR = ntoarmv7-ar cqs +QMAKE_OBJCOPY = ntoarmv7-objcopy +QMAKE_RANLIB = ntoarmv7-ranlib + +QMAKE_STRIP = ntoarmv7-strip + +load(qt_config) diff --git a/mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h b/mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h new file mode 100644 index 0000000000..8ef80c4bd7 --- /dev/null +++ b/mkspecs/unsupported/qnx-armv7le-qcc/qplatformdefs.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion Limited. +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +#include + +#define __STDC_CONSTANT_MACROS + +// We are hot - unistd.h should have turned on the specific APIs we requested + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// QNX doesn't have the System V header. This is not a standard +// POSIX header, it's only documented in the Single UNIX Specification. +// The preferred POSIX compliant way to share memory is to use the functions +// in that comply with the POSIX Real Time Interface (1003.1b). +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +// for htonl +#include + +#define QT_USE_XOPEN_LFS_EXTENSIONS +#define QT_NO_READDIR64 +#include "../../common/posix/qplatformdefs.h" + +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf + +// QNX6 doesn't have getpagesize() +inline int getpagesize() +{ + return ::sysconf(_SC_PAGESIZE); +} + +#include + +#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/qnx-g++/qmake.conf b/mkspecs/unsupported/qnx-g++/qmake.conf deleted file mode 100644 index bc96c21e9f..0000000000 --- a/mkspecs/unsupported/qnx-g++/qmake.conf +++ /dev/null @@ -1,58 +0,0 @@ -# -# qmake configuration for qnx-g++ -# -# Written for QNX RTOS v6 with X11 -# - -MAKEFILE_GENERATOR = UNIX -TARGET_PLATFORM = unix -TEMPLATE = app -CONFIG += qt warn_on release link_prl -QT += core gui - -include(../common/gcc-base-unix.conf) -include(../common/g++-unix.conf) -include(../common/unix.conf) - -QMAKE_CFLAGS_THREAD = -D_REENTRANT -QMAKE_CXXFLAGS_THREAD = $$QMAKE_CLFAGS_THREAD -QMAKE_COMPILER_DEFINES += __QNXNTO__ - -QMAKE_INCDIR = -QMAKE_LIBDIR = -QMAKE_INCDIR_X11 = /opt/X11R6/include -QMAKE_LIBDIR_X11 = /opt/X11R6/lib -QMAKE_INCDIR_QT = $$[QT_INSTALL_HEADERS] -QMAKE_LIBDIR_QT = $$[QT_INSTALL_LIBS] -QMAKE_INCDIR_OPENGL = /opt/X11R6/include -QMAKE_LIBDIR_OPENGL = /opt/X11R6/lib - -#QMAKE_LIBS = -lunix -QMAKE_LIBS = -QMAKE_LIBS_DYNLOAD = -QMAKE_LIBS_X11 = -lXext -lX11 -lm -lsocket -QMAKE_LIBS_X11SM = -lSM -lICE -QMAKE_LIBS_OPENGL = -lGL -QMAKE_LIBS_OPENGL_QT = -lGL -QMAKE_LIBS_THREAD = -QMAKE_LIBS_NETWORK = -lsocket - -QMAKE_AR = ar cqs -QMAKE_RANLIB = - -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f - -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $(COPY) -QMAKE_COPY_DIR = $(COPY) -r -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -QMAKE_STRIP = strip -QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_CHK_DIR_EXISTS = test -d -QMAKE_MKDIR = mkdir -p -load(qt_config) diff --git a/mkspecs/unsupported/qnx-g++/qplatformdefs.h b/mkspecs/unsupported/qnx-g++/qplatformdefs.h deleted file mode 100644 index 489e1be114..0000000000 --- a/mkspecs/unsupported/qnx-g++/qplatformdefs.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the qmake spec of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPLATFORMDEFS_H -#define QPLATFORMDEFS_H - -// Get Qt defines/settings - -#include "qglobal.h" - -// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs - -#include - - -// We are hot - unistd.h should have turned on the specific APIs we requested - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -// QNX doesn't have the System V header. This is not a standard -// POSIX header, it's only documented in the Single UNIX Specification. -// The preferred POSIX compliant way to share memory is to use the functions -// in that comply with the POSIX Real Time Interface (1003.1b). -#include -#include -#include -#include -#include -#ifndef QT_NO_IPV6IFNAME -#include -#endif - -// for htonl -#include - -#define QT_USE_XOPEN_LFS_EXTENSIONS -#include "../../common/posix/qplatformdefs.h" - -#define QT_SNPRINTF ::snprintf -#define QT_VSNPRINTF ::vsnprintf - -// QNX6 doesn't have getpagesize() -inline int getpagesize() -{ - return ::sysconf(_SC_PAGESIZE); -} - -#include - -// QNX6 doesn't have strtof - use strtod instead -inline float strtof(const char *b, char **e) -{ - return float(strtod(b, e)); -} - -#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) - -#endif // QPLATFORMDEFS_H diff --git a/mkspecs/unsupported/qnx-x86-qcc/qmake.conf b/mkspecs/unsupported/qnx-x86-qcc/qmake.conf new file mode 100644 index 0000000000..fef8d443c1 --- /dev/null +++ b/mkspecs/unsupported/qnx-x86-qcc/qmake.conf @@ -0,0 +1,25 @@ +# +# qmake configuration for qnx-qcc x86 targets +# + +MAKEFILE_GENERATOR = UNIX +TARGET_PLATFORM = unix +TEMPLATE = app +CONFIG += qt warn_on release link_prl +QT += core gui + +include(../../common/g++-unix.conf) +include(../../common/unix.conf) + +QMAKE_CC = qcc -Vgcc_ntox86 +QNX_CPUDIR = x86 + +include(../../common/qcc-base-qnx.conf) + +QMAKE_AR = ntox86-ar cqs +QMAKE_OBJCOPY = ntox86-objcopy +QMAKE_RANLIB = ntox86-ranlib + +QMAKE_STRIP = ntox86-strip + +load(qt_config) diff --git a/mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h b/mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h new file mode 100644 index 0000000000..8ef80c4bd7 --- /dev/null +++ b/mkspecs/unsupported/qnx-x86-qcc/qplatformdefs.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion Limited. +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs + +#include + +#define __STDC_CONSTANT_MACROS + +// We are hot - unistd.h should have turned on the specific APIs we requested + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// QNX doesn't have the System V header. This is not a standard +// POSIX header, it's only documented in the Single UNIX Specification. +// The preferred POSIX compliant way to share memory is to use the functions +// in that comply with the POSIX Real Time Interface (1003.1b). +#include +#include +#include +#include +#include +#ifndef QT_NO_IPV6IFNAME +#include +#endif + +// for htonl +#include + +#define QT_USE_XOPEN_LFS_EXTENSIONS +#define QT_NO_READDIR64 +#include "../../common/posix/qplatformdefs.h" + +#define QT_SNPRINTF ::snprintf +#define QT_VSNPRINTF ::vsnprintf + +// QNX6 doesn't have getpagesize() +inline int getpagesize() +{ + return ::sysconf(_SC_PAGESIZE); +} + +#include + +#define QT_QWS_TEMP_DIR QString::fromLatin1(qgetenv("TMP")) + +#endif // QPLATFORMDEFS_H -- cgit v1.2.3 From a47d974e19512ae5a445f64fbd2b1703201f781d Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 16 Feb 2012 23:49:27 +0100 Subject: QRegularExpression: fix optimizePattern, document the issue The studyData pointer is atomically set by the pointer assignment, but another processor running a different thread might see the new studyData value but not the memory it points to. Therefore, the current studyData is returned from optimizePattern and used by that thread. Docs were added to optimizePattern to explain what's going on. Change-Id: I4502c336077bb98a1751011aa93ffd4f585ed101 Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 7faa907e35..0252a30c89 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -773,7 +773,7 @@ struct QRegularExpressionPrivate : QSharedData void cleanCompiledPattern(); void compilePattern(); void getPatternInfo(); - void optimizePattern(); + pcre16_extra *optimizePattern(); QRegularExpressionMatchPrivate *doMatch(const QString &subject, int offset, @@ -1006,15 +1006,30 @@ static bool isJitEnabled() /*! \internal + + The purpose of the function is to call pcre16_study (which allows some + optimizations to be performed, including JIT-compiling the pattern), and + setting the studyData member variable to the result of the study. It gets + called by doMatch() every time a match is performed. As of now, the + optimizations on the pattern are performed after a certain number of usages + (i.e. the OPTIMIZE_AFTER_USE_COUNT constant). + + Notice that although the method is protected by a mutex, one thread may + invoke this function and return immediately (i.e. not study the pattern, + leaving studyData to NULL); but before calling pcre16_exec to perform the + match, another thread performs the studying and sets studyData to something + else. Although the assignment to studyData is itself atomic, the release of + the memory pointed by studyData isn't. Therefore, the current studyData + value is returned and used by doMatch. */ -void QRegularExpressionPrivate::optimizePattern() +pcre16_extra *QRegularExpressionPrivate::optimizePattern() { Q_ASSERT(compiledPattern); QMutexLocker lock(&mutex); if (studyData || (++usedCount != OPTIMIZE_AFTER_USE_COUNT)) - return; + return studyData; static const bool enableJit = isJitEnabled(); @@ -1027,6 +1042,8 @@ void QRegularExpressionPrivate::optimizePattern() if (!studyData && err) qWarning("QRegularExpressionPrivate::optimizePattern(): pcre_study failed: %s", err); + + return studyData; } /*! @@ -1089,7 +1106,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString capturingCount); // this is mutex protected - const_cast(this)->optimizePattern(); + const pcre16_extra *currentStudyData = const_cast(this)->optimizePattern(); int pcreOptions = convertToPcreOptions(matchOptions); @@ -1113,12 +1130,12 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int result; if (!previousMatchWasEmpty) { - result = pcre16_exec(compiledPattern, studyData, + result = pcre16_exec(compiledPattern, currentStudyData, subjectUtf16, subjectLength, offset, pcreOptions, captureOffsets, captureOffsetsCount); } else { - result = pcre16_exec(compiledPattern, studyData, + result = pcre16_exec(compiledPattern, currentStudyData, subjectUtf16, subjectLength, offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, captureOffsets, captureOffsetsCount); @@ -1136,7 +1153,7 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString ++offset; } - result = pcre16_exec(compiledPattern, studyData, + result = pcre16_exec(compiledPattern, currentStudyData, subjectUtf16, subjectLength, offset, pcreOptions, captureOffsets, captureOffsetsCount); -- cgit v1.2.3 From 3ae2dce9118c0d37cdfed60b07c83cdd20ef3e36 Mon Sep 17 00:00:00 2001 From: Sarah Smith Date: Tue, 6 Mar 2012 11:51:22 +1000 Subject: Compile with -qtnamespace Mac has to work with -qtnamespace as well, and other files have gotten this right, so follow their example. Change-Id: I551e1843e8a0e82a82d1d5ea8c8cd5f20e6880fa Reviewed-by: Rohan McGovern --- src/plugins/platforms/cocoa/qcocoasystemsettings.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index eea2fb6f5d..d5b2fce2e7 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -45,6 +45,8 @@ #include +QT_BEGIN_NAMESPACE + QColor qt_mac_colorFromCGColor(CGColorRef cgcolor) { QColor pc; @@ -144,7 +146,6 @@ QPalette * qt_mac_createSystemPalette() return palette; } - struct QMacPaletteMap { inline QMacPaletteMap(QPlatformTheme::Palette p, ThemeBrush a, ThemeBrush i) : paletteRole(p), active(a), inactive(i) { } @@ -227,3 +228,5 @@ QHash qt_mac_createRolePalettes() } return palettes; } + +QT_END_NAMESPACE -- cgit v1.2.3 From dd7a06d0c9eda4bdda2db3160930d8267d1bb821 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 1 Mar 2012 14:37:50 +1000 Subject: Refactor headersclean for usage from modules other than qtbase headersclean enforces various rules which all Qt headers are supposed to abide by. It fails compilation if these rules are broken. These rules should be followed also by modules hosted outside of qtbase. Split the test up so that it can be easily reused by other modules. Change-Id: Icf09cbfde411c926ed87914dc821e6dfc569b0de Reviewed-by: Jason McDonald --- tests/auto/other/headersclean/headersclean.pri | 38 ++++++++++++ tests/auto/other/headersclean/headersclean.pro | 28 +-------- .../other/headersclean/qt_headersclean_headers.h | 70 ++++++++++++++++++++++ tests/auto/other/headersclean/tst_headersclean.cpp | 36 ++--------- tests/auto/other/headersclean/tst_headersclean.h | 61 +++++++++++++++++++ tests/auto/other/other.pro | 3 +- 6 files changed, 176 insertions(+), 60 deletions(-) create mode 100644 tests/auto/other/headersclean/headersclean.pri create mode 100644 tests/auto/other/headersclean/qt_headersclean_headers.h create mode 100644 tests/auto/other/headersclean/tst_headersclean.h diff --git a/tests/auto/other/headersclean/headersclean.pri b/tests/auto/other/headersclean/headersclean.pri new file mode 100644 index 0000000000..163ef6d409 --- /dev/null +++ b/tests/auto/other/headersclean/headersclean.pri @@ -0,0 +1,38 @@ +# The headersclean test attempts to ensure all public Qt headers +# abide by various rules. +# +# To reuse this test outside of the qtbase module, +# include this .pri and create a qt_headersclean_headers.h which includes +# the headers you'd like to test. + +*-g++*: QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror + +# The flags here come from http://wiki.qt-project.org/Coding_Conventions#Conventions_for_public_header_files +# -Wold-style-cast cannot be used, /usr/include/bits/byteswap.h defines the macro bswap_16 using C style casts :( +# -Wfloat-equal cannot be used, qrect.h and qvector2d.h do exact comparisons in isNull and operator==. Would need #pragmas. +*-g++*: QMAKE_CXXFLAGS += -Woverloaded-virtual -Wshadow -Wundef + +# Other nice flags +*-g++*: QMAKE_CXXFLAGS += -Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wpointer-arith -Wformat-security + +# Enable pedantic mode, but accept variadic macros and 'long long' usage. +*-g++*: QMAKE_CXXFLAGS += -Wno-long-long -Wno-variadic-macros -pedantic-errors + +# There are outstanding alignment issues on ARM in some container classes. +contains(QT_ARCH,arm):*-g++*:QMAKE_CXXFLAGS -= -Wcast-align + +QMAKE_CXXFLAGS += -DQT_NO_CAST_TO_ASCII \ + -DQT_NO_CAST_FROM_ASCII \ + -DQT_STRICT_ITERATORS \ + -DQT_NO_URL_CAST_FROM_STRING \ + -DQT_NO_CAST_FROM_BYTEARRAY \ + -DQT_NO_KEYWORDS \ + -DQT_USE_FAST_CONCATENATION \ + -DQT_USE_FAST_OPERATOR_PLUS + +TARGET = tst_headersclean +SOURCES += $$PWD/tst_headersclean.cpp +HEADERS += $$PWD/tst_headersclean.h + +# qt_headersclean_headers.h should be alongside the .pro file +INCLUDEPATH += $$_PRO_FILE_PWD_ diff --git a/tests/auto/other/headersclean/headersclean.pro b/tests/auto/other/headersclean/headersclean.pro index 5444bebfb9..9bfadca08c 100644 --- a/tests/auto/other/headersclean/headersclean.pro +++ b/tests/auto/other/headersclean/headersclean.pro @@ -1,28 +1,2 @@ -CONFIG += testcase -TARGET = tst_headersclean -SOURCES += tst_headersclean.cpp - -# No need to link to all modules, only those actually used QT = core testlib gui widgets - -*-g++*: QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror - -# The flags here come from http://wiki.qt-project.org/Coding_Conventions#Conventions_for_public_header_files -# -Wold-style-cast cannot be used, /usr/include/bits/byteswap.h defines the macro bswap_16 using C style casts :( -# -Wfloat-equal cannot be used, qrect.h and qvector2d.h do exact comparisons in isNull and operator==. Would need #pragmas. -*-g++*: QMAKE_CXXFLAGS += -Woverloaded-virtual -Wshadow -Wundef - -# Other nice flags -*-g++*: QMAKE_CXXFLAGS += -Wnon-virtual-dtor -ansi -Wcast-align -Wchar-subscripts -Wpointer-arith -Wformat-security - -# Enable pedantic mode, but accept variadic macros and 'long long' usage. -*-g++*: QMAKE_CXXFLAGS += -Wno-long-long -Wno-variadic-macros -pedantic-errors - -QMAKE_CXXFLAGS += -DQT_NO_CAST_TO_ASCII \ - -DQT_NO_CAST_FROM_ASCII \ - -DQT_STRICT_ITERATORS \ - -DQT_NO_URL_CAST_FROM_STRING \ - -DQT_NO_CAST_FROM_BYTEARRAY \ - -DQT_NO_KEYWORDS \ - -DQT_USE_FAST_CONCATENATION \ - -DQT_USE_FAST_OPERATOR_PLUS +include(headersclean.pri) diff --git a/tests/auto/other/headersclean/qt_headersclean_headers.h b/tests/auto/other/headersclean/qt_headersclean_headers.h new file mode 100644 index 0000000000..c9b4e3f399 --- /dev/null +++ b/tests/auto/other/headersclean/qt_headersclean_headers.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_HEADERSCLEAN_HEADERS +#define QT_HEADERSCLEAN_HEADERS + +/* + This file should include all the headers to be tested by the headersclean + test. It may be copied and customized for each module. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_OPENGL +#include +#endif + +#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX) +#include +#endif + +#endif diff --git a/tests/auto/other/headersclean/tst_headersclean.cpp b/tests/auto/other/headersclean/tst_headersclean.cpp index 81d0aa3a4a..d442ad39d3 100644 --- a/tests/auto/other/headersclean/tst_headersclean.cpp +++ b/tests/auto/other/headersclean/tst_headersclean.cpp @@ -39,38 +39,12 @@ ** ****************************************************************************/ -#define signals int -#define slots int -#define emit public:; -#define foreach public:; -#define forever public:; +#include "tst_headersclean.h" +#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifndef QT_NO_OPENGL -#include -#endif - -#if !defined(QT_NO_DBUS) && defined(Q_OS_UNIX) -#include -#endif - -class tst_HeadersClean: public QObject +void tst_HeadersClean::initTestCase() { - Q_OBJECT -public: - tst_HeadersClean() {} -}; + QWARN("This is a compile test only"); +} QTEST_MAIN(tst_HeadersClean) -#include "tst_headersclean.moc" diff --git a/tests/auto/other/headersclean/tst_headersclean.h b/tests/auto/other/headersclean/tst_headersclean.h new file mode 100644 index 0000000000..7479e061dc --- /dev/null +++ b/tests/auto/other/headersclean/tst_headersclean.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_HEADERSCLEAN_H +#define TST_HEADERSCLEAN_H + +#define signals int +#define slots int +#define emit public:; +#define foreach public:; +#define forever public:; + +#include +#include + +class tst_HeadersClean: public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); +}; + +#endif diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 9ec5ea8e34..6c708baa6b 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -30,8 +30,7 @@ testcocoon: SUBDIRS -= headersclean cross_compile: SUBDIRS -= \ atwrapper \ - compiler \ - headersclean \ + compiler wince*|!contains(QT_CONFIG, accessibility):SUBDIRS -= qaccessibility -- cgit v1.2.3 From 678ab52ccba0b6a6903e9aee404dbe84fb74c91d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 2 Mar 2012 10:46:57 +0100 Subject: Improve type detection for query results When an aggregate function is used for a column in a SQL resultset then it should ensure that the right data type is reported for that column. This also concerns expressions when the returned column does not map directly to a table column. Test included for this. Task-number: QTBUG-22038 Change-Id: I07487694c0ed393d46af06e232914fe923356a99 Reviewed-by: Mark Brand Reviewed-by: Honglei Zhang --- src/sql/drivers/sqlite/qsql_sqlite.cpp | 33 +++++- tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 118 ++++++++++++++++++++++ 2 files changed, 147 insertions(+), 4 deletions(-) diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index d2dc5af070..b2a55252ac 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -174,12 +174,37 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset) // must use typeName for resolving the type to match QSqliteDriver::record QString typeName = QString(reinterpret_cast( sqlite3_column_decltype16(stmt, i))); - - int dotIdx = colName.lastIndexOf(QLatin1Char('.')); - QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName)); - // sqlite3_column_type is documented to have undefined behavior if the result set is empty int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i); + + QVariant::Type fieldType; + + if (!typeName.isEmpty()) { + fieldType = qGetColumnType(typeName); + } else { + // Get the proper type for the field based on stp value + switch (stp) { + case SQLITE_INTEGER: + fieldType = QVariant::Int; + break; + case SQLITE_FLOAT: + fieldType = QVariant::Double; + break; + case SQLITE_BLOB: + fieldType = QVariant::ByteArray; + break; + case SQLITE_TEXT: + fieldType = QVariant::String; + break; + case SQLITE_NULL: + default: + fieldType = QVariant::Invalid; + break; + } + } + + int dotIdx = colName.lastIndexOf(QLatin1Char('.')); + QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), fieldType); fld.setSqlType(stp); rInf.append(fld); } diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index b22e876c3c..584fcb045a 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -222,6 +222,8 @@ private slots: void sqlite_real_data() { generic_data("QSQLITE"); } void sqlite_real(); + void aggregateFunctionTypes_data() { generic_data(); } + void aggregateFunctionTypes(); private: // returns all database connections void generic_data(const QString &engine=QString()); @@ -3339,5 +3341,121 @@ void tst_QSqlQuery::sqlite_real() QCOMPARE(q.value(0).toDouble(), 5.6); } +void tst_QSqlQuery::aggregateFunctionTypes() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + { + const QString tableName(qTableName("numericFunctionsWithIntValues", __FILE__)); + tst_Databases::safeDropTable( db, tableName ); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id INTEGER)")); + + // First test without any entries + QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.record().field(0).type(), QVariant::Invalid); + + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (1)")); + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (2)")); + + QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 3); + QCOMPARE(q.record().field(0).type(), QVariant::Int); + + QVERIFY_SQL(q, exec("SELECT AVG(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 1.5); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT COUNT(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 2); + QCOMPARE(q.record().field(0).type(), QVariant::Int); + + QVERIFY_SQL(q, exec("SELECT MIN(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 1); + QCOMPARE(q.record().field(0).type(), QVariant::Int); + + QVERIFY_SQL(q, exec("SELECT MAX(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 2); + QCOMPARE(q.record().field(0).type(), QVariant::Int); + } + { + const QString tableName(qTableName("numericFunctionsWithDoubleValues", __FILE__)); + tst_Databases::safeDropTable( db, tableName ); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id DOUBLE)")); + + // First test without any entries + QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.record().field(0).type(), QVariant::Invalid); + + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (1.5)")); + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id) VALUES (2.5)")); + + QVERIFY_SQL(q, exec("SELECT SUM(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 4.0); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT AVG(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 2.0); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT COUNT(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), 2); + QCOMPARE(q.record().field(0).type(), QVariant::Int); + + QVERIFY_SQL(q, exec("SELECT MIN(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 1.5); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT MAX(id) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 2.5); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT ROUND(id, 1) FROM " + tableName + " WHERE id=1.5")); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 1.5); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + + QVERIFY_SQL(q, exec("SELECT ROUND(id, 0) FROM " + tableName + " WHERE id=2.5")); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toDouble(), 3.0); + QCOMPARE(q.record().field(0).type(), QVariant::Double); + } + { + const QString tableName(qTableName("stringFunctions", __FILE__)); + tst_Databases::safeDropTable( db, tableName ); + + QSqlQuery q(db); + QVERIFY_SQL(q, exec("CREATE TABLE " + tableName + " (id INTEGER, txt VARCHAR(50))")); + + QVERIFY_SQL(q, exec("SELECT MAX(txt) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.record().field(0).type(), QVariant::Invalid); + + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, txt) VALUES (1, 'lower')")); + QVERIFY_SQL(q, exec("INSERT INTO " + tableName + " (id, txt) VALUES (2, 'upper')")); + + QVERIFY_SQL(q, exec("SELECT MAX(txt) FROM " + tableName)); + QVERIFY(q.next()); + QCOMPARE(q.value(0).toString(), QLatin1String("upper")); + QCOMPARE(q.record().field(0).type(), QVariant::String); + } +} + QTEST_MAIN( tst_QSqlQuery ) #include "tst_qsqlquery.moc" -- cgit v1.2.3 From 79c0d9adbec05b0d6648e74952a862fa72b13c63 Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Wed, 7 Mar 2012 00:24:08 +0100 Subject: QSqlTableModel::selectRow(): complete documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mention in changes and document Qt version (merci à dfaure). Follow-up to 291e2c7d5416af4d16dc0a6e60df7980ba745a3d. Change-Id: Ie5626e9cd268812c1173ca494ccd8d6bd9be2687 Reviewed-by: Honglei Zhang --- dist/changes-5.0.0 | 3 +++ src/sql/models/qsqltablemodel.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 33a8869397..500e97085b 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -406,6 +406,9 @@ ignore the rest of the range. QSqlTableModel::indexInQuery() as example of how to implement in a subclass. +* QSqlTableModel::selectRow(): This is a new method that refreshes a single +row in the model from the database. + * QSqlTableModel edit strategies OnFieldChange/OnRowChange QTBUG-2875 Previously, after changes were submitted in these edit strategies, select() was called which removed and inserted all rows. This ruined navigation diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index aa7dc3dcf8..d39df1d710 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -392,6 +392,8 @@ bool QSqlTableModel::select() } /*! + \since 5.0 + Refreshes \a row in the model with values from the database table row matching on primary key values. Without a primary key, all column values must match. If no matching row is found, the model will show an empty row. -- cgit v1.2.3 From 7df2422fa4ec32daf421af1f3cb4f36e13234b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 6 Mar 2012 15:06:33 +0100 Subject: Remove abuse of QMetaTypeId from tst_qshortcut test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Q_DECLARE_METATYPE macro is much better for a custom type registration then a handwritten template specialization. Change-Id: Ia15688d89f708fbff0c1da93e08052d31f3b3fc0 Reviewed-by: Stephen Kelly Reviewed-by: Samuel Rødal --- tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp | 73 +++++++++++------------ 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp index 7a87266b8b..61efb6e3f3 100644 --- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp @@ -151,14 +151,9 @@ protected: Result ambigResult; }; -QT_BEGIN_NAMESPACE -template<> struct QMetaTypeId : public QMetaTypeId -{ static inline int qt_metatype_id() { return QMetaType::Int; } }; -template<> struct QMetaTypeId : public QMetaTypeId -{ static inline int qt_metatype_id() { return QMetaType::Int; } }; -template<> struct QMetaTypeId : public QMetaTypeId -{ static inline int qt_metatype_id() { return QMetaType::Int; } }; -QT_END_NAMESPACE +Q_DECLARE_METATYPE(tst_QShortcut::Widget); +Q_DECLARE_METATYPE(tst_QShortcut::Result); +Q_DECLARE_METATYPE(tst_QShortcut::Action); class TestEdit : public QTextEdit { @@ -249,8 +244,8 @@ Qt::KeyboardModifiers tst_QShortcut::toButtons( int key ) void tst_QShortcut::defElements() { - QTest::addColumn("action"); - QTest::addColumn("testWidget"); + QTest::addColumn("action"); + QTest::addColumn("testWidget"); QTest::addColumn("txt"); QTest::addColumn("k1"); QTest::addColumn("c1"); @@ -260,7 +255,7 @@ void tst_QShortcut::defElements() QTest::addColumn("c3"); QTest::addColumn("k4"); QTest::addColumn("c4"); - QTest::addColumn("result"); + QTest::addColumn("result"); } void tst_QShortcut::number() @@ -285,7 +280,7 @@ void tst_QShortcut::number_data() defElements(); // Clear all - QTest::newRow("N00 - clear") << ClearAll <<0< Date: Wed, 7 Mar 2012 09:49:20 +0100 Subject: Fix support for scripts that require OpenType We need to load OpenType tables when initializing fonts for scripts that require them. This fixes support for many Brahmic scripts. Change-Id: Ib5e50f2c7e5edb4b3e3ecf9fd004f2cf62634add Reviewed-by: Lars Knoll --- src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp | 2 +- src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index 5cfbc6cb4f..ebe73bff16 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -229,7 +229,7 @@ QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTab delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->harfbuzzFace(); + HB_Face hbFace = engine->initializedHarfbuzzFace(); if (!hbFace || !hbFace->supported_scripts[script]) { delete engine; engine = 0; diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 8a9670118f..69ec3ba08a 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -575,7 +575,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->harfbuzzFace(); + HB_Face hbFace = engine->initializedHarfbuzzFace(); if (!hbFace || !hbFace->supported_scripts[script]) { delete engine; engine = 0; -- cgit v1.2.3 From f72cbc7ce476b48f75a2b8b31c3e3ea0ac96bd11 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 7 Mar 2012 10:33:16 +0200 Subject: Make QCursor manual tests compile on Qt5 These tests were not aware widgets had been split to different lib. Change-Id: I58bde1304c876319a3cbb50f4d6a66e9f24b2886 Reviewed-by: Friedemann Kleint --- tests/manual/qcursor/allcursors/allcursors.pro | 2 +- tests/manual/qcursor/allcursors/main.cpp | 2 +- tests/manual/qcursor/allcursors/mainwindow.h | 2 +- tests/manual/qcursor/grab_override/grab_override.pro | 2 +- tests/manual/qcursor/grab_override/main.cpp | 2 +- tests/manual/qcursor/grab_override/mainwindow.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/manual/qcursor/allcursors/allcursors.pro b/tests/manual/qcursor/allcursors/allcursors.pro index 8e7da30752..b9f6a0c98d 100644 --- a/tests/manual/qcursor/allcursors/allcursors.pro +++ b/tests/manual/qcursor/allcursors/allcursors.pro @@ -6,7 +6,7 @@ TARGET = tst_allcursors TEMPLATE = app - +QT = core gui widgets SOURCES += main.cpp\ mainwindow.cpp diff --git a/tests/manual/qcursor/allcursors/main.cpp b/tests/manual/qcursor/allcursors/main.cpp index 8872481e88..fab9a7d3d7 100644 --- a/tests/manual/qcursor/allcursors/main.cpp +++ b/tests/manual/qcursor/allcursors/main.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include +#include #include "mainwindow.h" int main(int argc, char *argv[]) diff --git a/tests/manual/qcursor/allcursors/mainwindow.h b/tests/manual/qcursor/allcursors/mainwindow.h index 938f744862..5908d26e17 100644 --- a/tests/manual/qcursor/allcursors/mainwindow.h +++ b/tests/manual/qcursor/allcursors/mainwindow.h @@ -42,7 +42,7 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include +#include class QTimer; diff --git a/tests/manual/qcursor/grab_override/grab_override.pro b/tests/manual/qcursor/grab_override/grab_override.pro index c0f69be5ad..d84e2ee2b8 100644 --- a/tests/manual/qcursor/grab_override/grab_override.pro +++ b/tests/manual/qcursor/grab_override/grab_override.pro @@ -6,7 +6,7 @@ TARGET = t_cursors TEMPLATE = app - +QT = core gui widgets SOURCES += main.cpp\ mainwindow.cpp diff --git a/tests/manual/qcursor/grab_override/main.cpp b/tests/manual/qcursor/grab_override/main.cpp index 8872481e88..fab9a7d3d7 100644 --- a/tests/manual/qcursor/grab_override/main.cpp +++ b/tests/manual/qcursor/grab_override/main.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include +#include #include "mainwindow.h" int main(int argc, char *argv[]) diff --git a/tests/manual/qcursor/grab_override/mainwindow.h b/tests/manual/qcursor/grab_override/mainwindow.h index c231e9583d..3eb7e26fd7 100644 --- a/tests/manual/qcursor/grab_override/mainwindow.h +++ b/tests/manual/qcursor/grab_override/mainwindow.h @@ -42,7 +42,7 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include +#include class QTimer; -- cgit v1.2.3 From e1b2755083c8b30d2062108ea490f9c49729cf3b Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 6 Mar 2012 22:06:30 +0100 Subject: itemview/itemmodels: make some constructors explicit This is a semi-automatic search, so I'm reasonably sure that all the exported ones have been caught. Change-Id: I38d7978f1fcf7513e802ed0042aa7a57a95b0060 Reviewed-by: Stephen Kelly --- src/corelib/itemmodels/qabstractproxymodel.h | 2 +- src/corelib/itemmodels/qsortfilterproxymodel.h | 2 +- src/corelib/itemmodels/qstringlistmodel.h | 2 +- src/widgets/itemviews/qcolumnview_p.h | 2 +- src/widgets/itemviews/qdatawidgetmapper.h | 2 +- src/widgets/itemviews/qitemeditorfactory.h | 2 +- src/widgets/itemviews/qstandarditemmodel.h | 2 +- src/widgets/itemviews/qtablewidget.h | 2 +- src/widgets/itemviews/qtreewidget.h | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index 3c82199038..d80fcb683c 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -59,7 +59,7 @@ class Q_CORE_EXPORT QAbstractProxyModel : public QAbstractItemModel Q_OBJECT public: - QAbstractProxyModel(QObject *parent = 0); + explicit QAbstractProxyModel(QObject *parent = 0); ~QAbstractProxyModel(); virtual void setSourceModel(QAbstractItemModel *sourceModel); diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h index 8c7433d307..f18b1fccb1 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -73,7 +73,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole) public: - QSortFilterProxyModel(QObject *parent = 0); + explicit QSortFilterProxyModel(QObject *parent = 0); ~QSortFilterProxyModel(); void setSourceModel(QAbstractItemModel *sourceModel); diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h index d8b3f87f4a..a6bc4e7bd3 100644 --- a/src/corelib/itemmodels/qstringlistmodel.h +++ b/src/corelib/itemmodels/qstringlistmodel.h @@ -57,7 +57,7 @@ class Q_CORE_EXPORT QStringListModel : public QAbstractListModel Q_OBJECT public: explicit QStringListModel(QObject *parent = 0); - QStringListModel(const QStringList &strings, QObject *parent = 0); + explicit QStringListModel(const QStringList &strings, QObject *parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const; diff --git a/src/widgets/itemviews/qcolumnview_p.h b/src/widgets/itemviews/qcolumnview_p.h index 5bdb74c56c..c3c79d35a3 100644 --- a/src/widgets/itemviews/qcolumnview_p.h +++ b/src/widgets/itemviews/qcolumnview_p.h @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE class QColumnViewPreviewColumn : public QAbstractItemView { public: - QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(0) { + explicit QColumnViewPreviewColumn(QWidget *parent) : QAbstractItemView(parent), previewWidget(0) { } void setPreviewWidget(QWidget *widget) { diff --git a/src/widgets/itemviews/qdatawidgetmapper.h b/src/widgets/itemviews/qdatawidgetmapper.h index e73d4b1044..3cb8f09510 100644 --- a/src/widgets/itemviews/qdatawidgetmapper.h +++ b/src/widgets/itemviews/qdatawidgetmapper.h @@ -66,7 +66,7 @@ class Q_WIDGETS_EXPORT QDataWidgetMapper: public QObject Q_PROPERTY(SubmitPolicy submitPolicy READ submitPolicy WRITE setSubmitPolicy) public: - QDataWidgetMapper(QObject *parent = 0); + explicit QDataWidgetMapper(QObject *parent = 0); ~QDataWidgetMapper(); void setModel(QAbstractItemModel *model); diff --git a/src/widgets/itemviews/qitemeditorfactory.h b/src/widgets/itemviews/qitemeditorfactory.h index aff8de3a4c..8bc1cc7df6 100644 --- a/src/widgets/itemviews/qitemeditorfactory.h +++ b/src/widgets/itemviews/qitemeditorfactory.h @@ -69,7 +69,7 @@ template class QItemEditorCreator : public QItemEditorCreatorBase { public: - inline QItemEditorCreator(const QByteArray &valuePropertyName); + inline explicit QItemEditorCreator(const QByteArray &valuePropertyName); inline QWidget *createWidget(QWidget *parent) const { return new T(parent); } inline QByteArray valuePropertyName() const { return propertyName; } diff --git a/src/widgets/itemviews/qstandarditemmodel.h b/src/widgets/itemviews/qstandarditemmodel.h index e374665f20..767665fd94 100644 --- a/src/widgets/itemviews/qstandarditemmodel.h +++ b/src/widgets/itemviews/qstandarditemmodel.h @@ -66,7 +66,7 @@ class Q_WIDGETS_EXPORT QStandardItem { public: QStandardItem(); - QStandardItem(const QString &text); + explicit QStandardItem(const QString &text); QStandardItem(const QIcon &icon, const QString &text); explicit QStandardItem(int rows, int columns = 1); virtual ~QStandardItem(); diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h index 3d08e204d1..0c6ed85fc9 100644 --- a/src/widgets/itemviews/qtablewidget.h +++ b/src/widgets/itemviews/qtablewidget.h @@ -84,7 +84,7 @@ class Q_WIDGETS_EXPORT QTableWidgetItem friend class QTableModel; public: enum ItemType { Type = 0, UserType = 1000 }; - QTableWidgetItem(int type = Type); + explicit QTableWidgetItem(int type = Type); explicit QTableWidgetItem(const QString &text, int type = Type); explicit QTableWidgetItem(const QIcon &icon, const QString &text, int type = Type); QTableWidgetItem(const QTableWidgetItem &other); diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h index c9654d3e8e..c5f1032728 100644 --- a/src/widgets/itemviews/qtreewidget.h +++ b/src/widgets/itemviews/qtreewidget.h @@ -69,7 +69,7 @@ class Q_WIDGETS_EXPORT QTreeWidgetItem public: enum ItemType { Type = 0, UserType = 1000 }; explicit QTreeWidgetItem(int type = Type); - QTreeWidgetItem(const QStringList &strings, int type = Type); + explicit QTreeWidgetItem(const QStringList &strings, int type = Type); explicit QTreeWidgetItem(QTreeWidget *view, int type = Type); QTreeWidgetItem(QTreeWidget *view, const QStringList &strings, int type = Type); QTreeWidgetItem(QTreeWidget *view, QTreeWidgetItem *after, int type = Type); -- cgit v1.2.3 From 7439fb47cd7c5731dd1aadeaf10c46b58aa59798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 6 Mar 2012 15:12:06 +0100 Subject: Add nicer error message in qMetaTypeId function. The function can be used only with a registered type and it would fail to compile for other types. By adding the static assert we can print an almost user friendly compilation error message. Change-Id: I59ab148cabf32afe0baef186b82cb03303b57780 Reviewed-by: Stephen Kelly Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 7f6eaf2230..eacb8403dc 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -484,6 +484,7 @@ inline int qMetaTypeId( #endif ) { + Q_STATIC_ASSERT_X(QMetaTypeId2::Defined, "Type is not registered, please use Q_DECLARE_METATYPE macro to make it know to Qt's meta-object system"); return QMetaTypeId2::qt_metatype_id(); } -- cgit v1.2.3 From 83cabda862dced9477d155c84df9440047c856cf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 7 Mar 2012 08:56:41 +0100 Subject: Add fonts to QPlatformTheme. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove QPlatformFontDatabase::defaultFonts() returning a hash containing widget name ->font and the Windows implementation. - Add enumeration and font accessor to QPlatformTheme. The value returned for the enumeration value overwrites the default font of the font database. - Implement for Windows, Mac and KDE. - Add more Windows palettes. Task-number: QTBUG-23686 Change-Id: I8a2abdfd216df23daa7c9630c54264cdf61295db Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qguiapplication.cpp | 5 + src/gui/kernel/qplatformtheme_qpa.cpp | 6 + src/gui/kernel/qplatformtheme_qpa.h | 28 ++++ src/gui/text/qplatformfontdatabase_qpa.cpp | 12 -- src/gui/text/qplatformfontdatabase_qpa.h | 2 +- .../themes/genericunix/qgenericunixthemes.cpp | 51 ++++++- .../themes/genericunix/qgenericunixthemes_p.h | 23 +++- src/plugins/platforms/cocoa/qcocoasystemsettings.h | 1 + .../platforms/cocoa/qcocoasystemsettings.mm | 40 ++++++ src/plugins/platforms/cocoa/qcocoatheme.h | 2 + src/plugins/platforms/cocoa/qcocoatheme.mm | 8 ++ .../platforms/windows/qtwindows_additional.h | 3 +- .../platforms/windows/qwindowsfontdatabase.cpp | 49 +------ .../platforms/windows/qwindowsfontdatabase.h | 1 - .../platforms/windows/qwindowsfontdatabase_ft.cpp | 40 +----- .../platforms/windows/qwindowsfontdatabase_ft.h | 5 +- src/plugins/platforms/windows/qwindowstheme.cpp | 148 +++++++++++++++++---- src/plugins/platforms/windows/qwindowstheme.h | 8 +- src/widgets/kernel/qapplication.cpp | 5 - src/widgets/kernel/qapplication_p.h | 6 +- src/widgets/kernel/qapplication_qpa.cpp | 54 ++++++++ src/widgets/widgets/qmdisubwindow.cpp | 2 +- .../widgets/itemviews/qlistview/tst_qlistview.cpp | 3 +- .../qstylesheetstyle/tst_qstylesheetstyle.cpp | 7 +- 24 files changed, 351 insertions(+), 158 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 095336a948..f5aea654fc 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -172,6 +172,11 @@ static inline void clearPalette() static void initFontUnlocked() { + if (!QGuiApplicationPrivate::app_font) { + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) + if (const QFont *font = theme->font(QPlatformTheme::SystemFont)) + QGuiApplicationPrivate::app_font = new QFont(*font); + } if (!QGuiApplicationPrivate::app_font) QGuiApplicationPrivate::app_font = new QFont(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFont()); diff --git a/src/gui/kernel/qplatformtheme_qpa.cpp b/src/gui/kernel/qplatformtheme_qpa.cpp index 3fdece70ea..c6314825d7 100644 --- a/src/gui/kernel/qplatformtheme_qpa.cpp +++ b/src/gui/kernel/qplatformtheme_qpa.cpp @@ -137,6 +137,12 @@ const QPalette *QPlatformTheme::palette(Palette type) const return 0; } +const QFont *QPlatformTheme::font(Font type) const +{ + Q_UNUSED(type) + return 0; +} + QVariant QPlatformTheme::themeHint(ThemeHint hint) const { switch (hint) { diff --git a/src/gui/kernel/qplatformtheme_qpa.h b/src/gui/kernel/qplatformtheme_qpa.h index be18e4fe38..6ac6a0f573 100644 --- a/src/gui/kernel/qplatformtheme_qpa.h +++ b/src/gui/kernel/qplatformtheme_qpa.h @@ -55,6 +55,7 @@ class QPlatformMenuBar; class QPlatformDialogHelper; class QVariant; class QPalette; +class QFont; class Q_GUI_EXPORT QPlatformTheme { @@ -102,6 +103,31 @@ public: NPalettes }; + enum Font { + SystemFont, + MenuFont, + MenuBarFont, + MenuItemFont, + MessageBoxFont, + LabelFont, + TipLabelFont, + StatusBarFont, + TitleBarFont, + MdiSubWindowTitleFont, + DockWidgetTitleFont, + PushButtonFont, + ToolButtonFont, + ItemViewFont, + ListViewFont, + HeaderViewFont, + ListBoxFont, + ComboMenuItemFont, + ComboLineEditFont, + SmallFont, + MiniFont, + NFonts + }; + enum KeyboardSchemes { WindowsKeyboardScheme, @@ -122,6 +148,8 @@ public: virtual const QPalette *palette(Palette type = SystemPalette) const; + virtual const QFont *font(Font type = SystemFont) const; + virtual QVariant themeHint(ThemeHint hint) const; }; diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp index 8fcf421330..47a9fe5ab1 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.cpp +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -374,18 +374,6 @@ QFont QPlatformFontDatabase::defaultFont() const return QFont(QLatin1String("Helvetica")); } -/*! - Returns fonts for class names. - - \sa QGuiApplication::font() - \since 5.0 -*/ - -QHash QPlatformFontDatabase::defaultFonts() const -{ - return QHash(); -} - /*! Resolve alias to actual font family names. diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h index 6a58a3106c..5a5a8f321f 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.h +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -100,7 +100,7 @@ public: virtual QString fontDir() const; virtual QFont defaultFont() const; - virtual QHash defaultFonts() const; + virtual QString resolveFontFamilyAlias(const QString &family) const; //callback diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp index 257fe9156f..602dd6264a 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp @@ -43,6 +43,7 @@ #include "../../services/genericunix/qgenericunixservices_p.h" #include +#include #include #include #include @@ -54,6 +55,20 @@ QT_BEGIN_NAMESPACE +ResourceHelper::ResourceHelper() +{ + qFill(palettes, palettes + QPlatformTheme::NPalettes, static_cast(0)); + qFill(fonts, fonts + QPlatformTheme::NFonts, static_cast(0)); +} + +void ResourceHelper::clear() +{ + qDeleteAll(palettes, palettes + QPlatformTheme::NPalettes); + qDeleteAll(fonts, fonts + QPlatformTheme::NFonts); + qFill(palettes, palettes + QPlatformTheme::NPalettes, static_cast(0)); + qFill(fonts, fonts + QPlatformTheme::NFonts, static_cast(0)); +} + /*! \class QGenericX11ThemeQKdeTheme \brief QGenericX11Theme is a generic theme implementation for X11. @@ -148,19 +163,40 @@ QKdeTheme::QKdeTheme(const QString &kdeHome, int kdeVersion) : m_kdeHome(kdeHome), m_kdeVersion(kdeVersion), m_toolButtonStyle(Qt::ToolButtonTextBesideIcon), m_toolBarIconSize(0) { - qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); refresh(); } -void QKdeTheme::clearPalettes() +static inline QFont *readKdeFontSetting(const QSettings &settings, const QString &key) { - qDeleteAll(m_palettes, m_palettes + NPalettes); - qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); + const QVariant fontValue = settings.value(key); + if (fontValue.isValid()) { + // Read font value: Might be a QStringList as KDE stores fonts without quotes. + // Also retrieve the family for the constructor since we cannot use the + // default constructor of QFont, which accesses QGuiApplication::systemFont() + // causing recursion. + QString fontDescription; + QString fontFamily; + if (fontValue.type() == QVariant::StringList) { + const QStringList list = fontValue.toStringList(); + if (!list.isEmpty()) { + fontFamily = list.first(); + fontDescription = list.join(QStringLiteral(",")); + } + } else { + fontDescription = fontFamily = fontValue.toString(); + } + if (!fontDescription.isEmpty()) { + QFont font(fontFamily); + if (font.fromString(fontDescription)) + return new QFont(font); + } + } + return 0; } void QKdeTheme::refresh() { - clearPalettes(); + m_resources.clear(); m_toolButtonStyle = Qt::ToolButtonTextBesideIcon; m_toolBarIconSize = 0; @@ -177,7 +213,7 @@ void QKdeTheme::refresh() QPalette systemPalette; if (readKdeSystemPalette(kdeSettings, &systemPalette)) - m_palettes[SystemPalette] = new QPalette(systemPalette); + m_resources.palettes[SystemPalette] = new QPalette(systemPalette); //## TODO tooltip color const QVariant styleValue = kdeSettings.value(QStringLiteral("widgetStyle")); @@ -205,6 +241,9 @@ void QKdeTheme::refresh() else if (toolBarStyle == QStringLiteral("TextUnderIcon")) m_toolButtonStyle = Qt::ToolButtonTextUnderIcon; } + + // Read system font, ignore 'fixed' 'smallestReadableFont' + m_resources.fonts[SystemFont] = readKdeFontSetting(kdeSettings, QStringLiteral("font")); } QString QKdeTheme::globalSettingsFile() const diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h index 12937a205f..a9db29e8cd 100644 --- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h +++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h @@ -50,6 +50,18 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +class ResourceHelper +{ +public: + ResourceHelper(); + ~ResourceHelper() { clear(); } + + void clear(); + + QPalette *palettes[QPlatformTheme::NPalettes]; + QFont *fonts[QPlatformTheme::NFonts]; +}; + class QGenericUnixTheme : public QPlatformTheme { public: @@ -66,21 +78,24 @@ class QKdeTheme : public QPlatformTheme { QKdeTheme(const QString &kdeHome, int kdeVersion); public: - ~QKdeTheme() { clearPalettes(); } static QPlatformTheme *createKdeTheme(); virtual QVariant themeHint(ThemeHint hint) const; + virtual const QPalette *palette(Palette type = SystemPalette) const - { return m_palettes[type]; } + { return m_resources.palettes[type]; } + + virtual const QFont *font(Font type) const + { return m_resources.fonts[type]; } private: QString globalSettingsFile() const; - void clearPalettes(); void refresh(); const QString m_kdeHome; const int m_kdeVersion; - QPalette *m_palettes[NPalettes]; + + ResourceHelper m_resources; QString m_iconThemeName; QString m_iconFallbackThemeName; QStringList m_styleNames; diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.h b/src/plugins/platforms/cocoa/qcocoasystemsettings.h index 2ed6f766aa..10cac27dcd 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.h +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.h @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE QPalette * qt_mac_createSystemPalette(); QHash qt_mac_createRolePalettes(); +QHash qt_mac_createRoleFonts(); QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index d5b2fce2e7..c2f5df4d38 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -42,6 +42,7 @@ #include "qcocoasystemsettings.h" #include +#include #include @@ -229,4 +230,43 @@ QHash qt_mac_createRolePalettes() return palettes; } +QFont *qt_mac_qfontForThemeFont(ThemeFontID themeID) +{ + CTFontUIFontType ctID = HIThemeGetUIFontType(themeID); + QCFType ctfont = CTFontCreateUIFontForLanguage(ctID, 0, 0); + QString familyName = QCFString(CTFontCopyFamilyName(ctfont)); + QCFType dict = CTFontCopyTraits(ctfont); + CFNumberRef num = static_cast(CFDictionaryGetValue(dict, kCTFontWeightTrait)); + float fW; + CFNumberGetValue(num, kCFNumberFloat32Type, &fW); + QFont::Weight wght = fW > 0. ? QFont::Bold : QFont::Normal; + num = static_cast(CFDictionaryGetValue(dict, kCTFontSlantTrait)); + CFNumberGetValue(num, kCFNumberFloatType, &fW); + bool italic = (fW != 0.0); + return new QFont(familyName, CTFontGetSize(ctfont), wght, italic); +} + +QHash qt_mac_createRoleFonts() +{ + QHash fonts; + + fonts.insert(QPlatformTheme::SystemFont, qt_mac_qfontForThemeFont(kThemeApplicationFont)); + fonts.insert(QPlatformTheme::PushButtonFont, qt_mac_qfontForThemeFont(kThemePushButtonFont)); + fonts.insert(QPlatformTheme::ListViewFont, qt_mac_qfontForThemeFont(kThemeViewsFont)); + fonts.insert(QPlatformTheme::ListBoxFont, qt_mac_qfontForThemeFont(kThemeViewsFont)); + fonts.insert(QPlatformTheme::TitleBarFont, qt_mac_qfontForThemeFont(kThemeWindowTitleFont)); + fonts.insert(QPlatformTheme::MenuFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont)); + fonts.insert(QPlatformTheme::ComboMenuItemFont, qt_mac_qfontForThemeFont(kThemeSystemFont)); + fonts.insert(QPlatformTheme::HeaderViewFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); + fonts.insert(QPlatformTheme::TipLabelFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); + fonts.insert(QPlatformTheme::LabelFont, qt_mac_qfontForThemeFont(kThemeSystemFont)); + fonts.insert(QPlatformTheme::ToolButtonFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); + fonts.insert(QPlatformTheme::MenuItemFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont)); + fonts.insert(QPlatformTheme::ComboLineEditFont, qt_mac_qfontForThemeFont(kThemeViewsFont)); + fonts.insert(QPlatformTheme::SmallFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont)); + fonts.insert(QPlatformTheme::MiniFont, qt_mac_qfontForThemeFont(kThemeMiniSystemFont)); + + return fonts; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index dccda2ce3b..030db1822c 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -61,11 +61,13 @@ public: QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const; const QPalette *palette(Palette type = SystemPalette) const; + const QFont *font(Font type = SystemFont) const; QVariant themeHint(ThemeHint hint) const; private: mutable QPalette *m_systemPalette; mutable QHash m_palettes; + mutable QHash m_fonts; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 71d7c9e294..8ec6e3801e 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -118,6 +118,14 @@ const QPalette *QCocoaTheme::palette(Palette type) const return 0; } +const QFont *QCocoaTheme::font(Font type) const +{ + if (m_fonts.isEmpty()) { + m_fonts = qt_mac_createRoleFonts(); + } + return m_fonts.value(type, 0); +} + QVariant QCocoaTheme::themeHint(ThemeHint hint) const { switch (hint) { diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h index d82240255e..ac768e2dab 100644 --- a/src/plugins/platforms/windows/qtwindows_additional.h +++ b/src/plugins/platforms/windows/qtwindows_additional.h @@ -61,7 +61,8 @@ # define FE_FONTSMOOTHINGCLEARTYPE 0x0002 # define CLEARTYPE_QUALITY 5 # define SPI_GETDROPSHADOW 0x1024 - +# define COLOR_MENUHILIGHT 29 +# define COLOR_MENUBAR 30 # define CF_DIBV5 17 #define CO_E_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80004021L) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index fba7794a12..5094ad9dc3 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qwindowsfontdatabase.h" +#include "qwindowsfontdatabase_ft.h" // for default font #include "qwindowscontext.h" #include "qwindowsfontengine.h" #include "qwindowsfontenginedirectwrite.h" @@ -1066,53 +1067,7 @@ static inline int verticalDPI() QFont QWindowsFontDatabase::defaultFont() const { - LOGFONT lf; - GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); - QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf); - // "MS Shell Dlg 2" is the correct system font >= Win2k - if (systemFont.family() == QStringLiteral("MS Shell Dlg")) - systemFont.setFamily(QStringLiteral("MS Shell Dlg 2")); - if (QWindowsContext::verboseFonts) - qDebug() << __FUNCTION__ << systemFont; - return systemFont; -} - -QHash QWindowsFontDatabase::defaultFonts() const -{ - QHash result; - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - - const int verticalRes = verticalDPI(); - - const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes); - const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes); - const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes); - const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes); - - LOGFONT lfIconTitleFont; - SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes); - - result.insert(QByteArray("QMenu"), menuFont); - result.insert(QByteArray("QMenuBar"), menuFont); - result.insert(QByteArray("QMessageBox"), messageFont); - result.insert(QByteArray("QTipLabel"), statusFont); - result.insert(QByteArray("QStatusBar"), statusFont); - result.insert(QByteArray("Q3TitleBar"), titleFont); - result.insert(QByteArray("QWorkspaceTitleBar"), titleFont); - result.insert(QByteArray("QAbstractItemView"), iconTitleFont); - result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont); - if (QWindowsContext::verboseFonts) { - typedef QHash::const_iterator CIT; - QDebug nsp = qDebug().nospace(); - nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n"; - const CIT cend = result.constEnd(); - for (CIT it = result.constBegin(); it != cend; ++it) - nsp << it.key() << ' ' << it.value() << '\n'; - } - return result; + return QWindowsFontDatabaseFT::systemDefaultFont(); } QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index b08b682991..04d6ccdd91 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -86,7 +86,6 @@ public: virtual QString fontDir() const; virtual QFont defaultFont() const; - virtual QHash defaultFonts() const; static QFontEngine *createEngine(int script, const QFontDef &request, HDC fontHdc, int dpi, bool rawMode, diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index e972ae23ee..fcce87d0bd 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -460,7 +460,7 @@ static inline int verticalDPI() return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY); } -QFont QWindowsFontDatabaseFT::defaultFont() const +QFont QWindowsFontDatabaseFT::systemDefaultFont() { LOGFONT lf; GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); @@ -473,44 +473,6 @@ QFont QWindowsFontDatabaseFT::defaultFont() const return systemFont; } -QHash QWindowsFontDatabaseFT::defaultFonts() const -{ - QHash result; - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - - const int verticalRes = verticalDPI(); - - const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes); - const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes); - const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes); - const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes); - - LOGFONT lfIconTitleFont; - SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes); - - result.insert(QByteArray("QMenu"), menuFont); - result.insert(QByteArray("QMenuBar"), menuFont); - result.insert(QByteArray("QMessageBox"), messageFont); - result.insert(QByteArray("QTipLabel"), statusFont); - result.insert(QByteArray("QStatusBar"), statusFont); - result.insert(QByteArray("Q3TitleBar"), titleFont); - result.insert(QByteArray("QWorkspaceTitleBar"), titleFont); - result.insert(QByteArray("QAbstractItemView"), iconTitleFont); - result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont); - if (QWindowsContext::verboseFonts) { - typedef QHash::const_iterator CIT; - QDebug nsp = qDebug().nospace(); - nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n"; - const CIT cend = result.constEnd(); - for (CIT it = result.constBegin(); it != cend; ++it) - nsp << it.key() << ' ' << it.value() << '\n'; - } - return result; -} - QFont QWindowsFontDatabaseFT::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In) { if (verticalDPI_In <= 0) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index 5a0c4c6377..4136b75dd8 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -59,8 +59,9 @@ public: QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); virtual QString fontDir() const; - virtual QFont defaultFont() const; - virtual QHash defaultFonts() const; + virtual QFont defaultFont() const { return systemDefaultFont(); } + static QFont systemDefaultFont(); + static HFONT systemFont(); static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0); diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 5350b3ca3f..10b4682ad8 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -44,6 +44,7 @@ #include "qwindowscontext.h" #include "qwindowsintegration.h" #include "qt_windows.h" +#include "qwindowsfontdatabase_ft.h" #include #include @@ -76,6 +77,22 @@ static inline QString paletteToString(const QPalette &palette) return result; } +static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue) +{ + BOOL result; + if (SystemParametersInfo(what, 0, &result, 0)) + return result ? true : false; + return defaultValue; +} + +static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue) +{ + DWORD result; + if (SystemParametersInfo(what, 0, &result, 0)) + return result; + return defaultValue; +} + static inline QColor mixColors(const QColor &c1, const QColor &c2) { return QColor ((c1.red() + c2.red()) / 2, @@ -138,7 +155,7 @@ static inline QPalette systemPalette() return result; } -QPalette toolTipPalette(const QPalette &systemPalette) +static inline QPalette toolTipPalette(const QPalette &systemPalette) { QPalette result(systemPalette); const QColor tipBgColor(getSysColor(COLOR_INFOBK)); @@ -163,24 +180,58 @@ QPalette toolTipPalette(const QPalette &systemPalette) return result; } -static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue) +static inline QPalette menuPalette(const QPalette &systemPalette) { - BOOL result; - if (SystemParametersInfo(what, 0, &result, 0)) - return result ? true : false; - return defaultValue; + QPalette result(systemPalette); + const QColor menuColor(getSysColor(COLOR_INFOBK)); + const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); + const QColor disabled(getSysColor(COLOR_GRAYTEXT)); + const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); + // we might need a special color group for the result. + result.setColor(QPalette::Active, QPalette::Button, menuColor); + result.setColor(QPalette::Active, QPalette::Text, menuTextColor); + result.setColor(QPalette::Active, QPalette::WindowText, menuTextColor); + result.setColor(QPalette::Active, QPalette::ButtonText, menuTextColor); + result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); + result.setColor(QPalette::Disabled, QPalette::Text, disabled); + result.setColor(QPalette::Disabled, QPalette::Highlight, + getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); + result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); + result.setColor(QPalette::Disabled, QPalette::Button, + result.color(QPalette::Active, QPalette::Button)); + result.setColor(QPalette::Inactive, QPalette::Button, + result.color(QPalette::Active, QPalette::Button)); + result.setColor(QPalette::Inactive, QPalette::Text, + result.color(QPalette::Active, QPalette::Text)); + result.setColor(QPalette::Inactive, QPalette::WindowText, + result.color(QPalette::Active, QPalette::WindowText)); + result.setColor(QPalette::Inactive, QPalette::ButtonText, + result.color(QPalette::Active, QPalette::ButtonText)); + result.setColor(QPalette::Inactive, QPalette::Highlight, + result.color(QPalette::Active, QPalette::Highlight)); + result.setColor(QPalette::Inactive, QPalette::HighlightedText, + result.color(QPalette::Active, QPalette::HighlightedText)); + result.setColor(QPalette::Inactive, QPalette::ButtonText, + systemPalette.color(QPalette::Inactive, QPalette::Dark)); + return result; } -static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue) +static inline QPalette *menuBarPalette(const QPalette &menuPalette) { - DWORD result; - if (SystemParametersInfo(what, 0, &result, 0)) - return result; - return defaultValue; + QPalette *result = 0; + if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) { + result = new QPalette(menuPalette); + const QColor menubar(getSysColor(COLOR_MENUBAR)); + result->setColor(QPalette::Active, QPalette::Button, menubar); + result->setColor(QPalette::Disabled, QPalette::Button, menubar); + result->setColor(QPalette::Inactive, QPalette::Button, menubar); + } + return result; } QWindowsTheme::QWindowsTheme() { + qFill(m_fonts, m_fonts + NFonts, static_cast(0)); qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); refresh(); } @@ -188,12 +239,7 @@ QWindowsTheme::QWindowsTheme() QWindowsTheme::~QWindowsTheme() { clearPalettes(); -} - -void QWindowsTheme::clearPalettes() -{ - qDeleteAll(m_palettes, m_palettes + NPalettes); - qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); + clearFonts(); } QWindowsTheme *QWindowsTheme::instance() @@ -243,17 +289,65 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const return QPlatformTheme::themeHint(hint); } -void QWindowsTheme::refresh() +void QWindowsTheme::clearPalettes() { - clearPalettes(); - if (QGuiApplication::desktopSettingsAware()) { - m_palettes[SystemPalette] = new QPalette(systemPalette()); - m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette])); - if (QWindowsContext::verboseTheming) - qDebug() << __FUNCTION__ << '\n' - << " system=" << paletteToString(*m_palettes[SystemPalette]) - << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]); - } + qDeleteAll(m_palettes, m_palettes + NPalettes); + qFill(m_palettes, m_palettes + NPalettes, static_cast(0)); +} + +void QWindowsTheme::refreshPalettes() +{ + + if (!QGuiApplication::desktopSettingsAware()) + return; + m_palettes[SystemPalette] = new QPalette(systemPalette()); + m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette])); + m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette])); + m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]); + if (QWindowsContext::verboseTheming) + qDebug() << __FUNCTION__ << '\n' + << " system=" << paletteToString(*m_palettes[SystemPalette]) + << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]); +} + +void QWindowsTheme::clearFonts() +{ + qDeleteAll(m_fonts, m_fonts + NFonts); + qFill(m_fonts, m_fonts + NFonts, static_cast(0)); +} + +void QWindowsTheme::refreshFonts() +{ + clearFonts(); + if (!QGuiApplication::desktopSettingsAware()) + return; + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); + + const QFont menuFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMenuFont); + const QFont messageBoxFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMessageFont); + const QFont statusFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfStatusFont); + const QFont titleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfCaptionFont); + + LOGFONT lfIconTitleFont; + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); + const QFont iconTitleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(lfIconTitleFont); + + m_fonts[SystemFont] = new QFont(QWindowsFontDatabaseFT::systemDefaultFont()); + m_fonts[MenuFont] = new QFont(menuFont); + m_fonts[MenuBarFont] = new QFont(menuFont); + m_fonts[MessageBoxFont] = new QFont(messageBoxFont); + m_fonts[TipLabelFont] = new QFont(statusFont); + m_fonts[StatusBarFont] = new QFont(statusFont); + m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont); + m_fonts[DockWidgetTitleFont] = new QFont(titleFont); + m_fonts[ItemViewFont] = new QFont(iconTitleFont); + + if (QWindowsContext::verboseTheming) + qDebug() << __FUNCTION__ << '\n' + << " menuFont=" << menuFont + << " messageBox=" << MessageBoxFont; } bool QWindowsTheme::usePlatformNativeDialog(DialogType type) const diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 950c380737..37346eed3a 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -64,14 +64,20 @@ public: virtual QVariant themeHint(ThemeHint) const; virtual const QPalette *palette(Palette type = SystemPalette) const { return m_palettes[type]; } + virtual const QFont *font(Font type = SystemFont) const + { return m_fonts[type]; } void windowsThemeChanged(QWindow *window); private: - void refresh(); + void refresh() { refreshPalettes(); refreshFonts(); } void clearPalettes(); + void refreshPalettes(); + void clearFonts(); + void refreshFonts(); QPalette *m_palettes[NPalettes]; + QFont *m_fonts[NFonts]; }; static inline COLORREF qColorToCOLORREF(const QColor &color) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index bf2729a6d8..90b64db579 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -431,11 +431,6 @@ PaletteHash *qt_app_palettes_hash() return app_palettes(); } -FontHash::FontHash() -{ - QHash::operator=(QGuiApplicationPrivate::platformIntegration()->fontDatabase()->defaultFonts()); -} - Q_GLOBAL_STATIC(FontHash, app_fonts) FontHash *qt_app_fonts_hash() { diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index ae4f0c2044..2d639172e2 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -157,10 +157,7 @@ QMacTabletHash *qt_mac_tablet_hash(); # endif #endif -struct FontHash : public QHash -{ - FontHash(); -}; +typedef QHash FontHash; FontHash *qt_app_fonts_hash(); typedef QHash PaletteHash; @@ -292,6 +289,7 @@ public: static void setSystemPalette(const QPalette &pal); static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash); static void initializeWidgetPaletteHash(); + static void initializeWidgetFontHash(); static void setSystemFont(const QFont &font); #if defined(Q_WS_X11) diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index 6c91b89674..97fc794252 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -318,6 +318,58 @@ void QApplicationPrivate::initializeWidgetPaletteHash() setPossiblePalette(platformTheme->palette(QPlatformTheme::TextLineEditPalette), "QLineEdit"); } +void QApplicationPrivate::initializeWidgetFontHash() +{ + const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); + if (!theme) + return; + FontHash *fontHash = qt_app_fonts_hash(); + if (const QFont *font = theme->font(QPlatformTheme::MenuFont)) + fontHash->insert(QByteArrayLiteral("QMenu"), *font); + if (const QFont *font = theme->font(QPlatformTheme::MenuBarFont)) + fontHash->insert(QByteArrayLiteral("QMenuBar"), *font); + if (const QFont *font = theme->font(QPlatformTheme::MenuItemFont)) + fontHash->insert(QByteArrayLiteral("QMenuItem"), *font); + if (const QFont *font = theme->font(QPlatformTheme::MessageBoxFont)) + fontHash->insert(QByteArrayLiteral("QMessageBox"), *font); + if (const QFont *font = theme->font(QPlatformTheme::LabelFont)) + fontHash->insert(QByteArrayLiteral("QLabel"), *font); + if (const QFont *font = theme->font(QPlatformTheme::TipLabelFont)) + fontHash->insert(QByteArrayLiteral("QTipLabel"), *font); + if (const QFont *font = theme->font(QPlatformTheme::TitleBarFont)) + fontHash->insert(QByteArrayLiteral("QTitleBar"), *font); + if (const QFont *font = theme->font(QPlatformTheme::StatusBarFont)) + fontHash->insert(QByteArrayLiteral("QStatusBar"), *font); + if (const QFont *font = theme->font(QPlatformTheme::MdiSubWindowTitleFont)) { + fontHash->insert(QByteArrayLiteral("QWorkspaceTitleBar"), *font); + fontHash->insert(QByteArrayLiteral("QMdiSubWindowTitleBar"), *font); + } + if (const QFont *font = theme->font(QPlatformTheme::DockWidgetTitleFont)) + fontHash->insert(QByteArrayLiteral("QDockWidgetTitle"), *font); + if (const QFont *font = theme->font(QPlatformTheme::PushButtonFont)) + fontHash->insert(QByteArrayLiteral("QPushButton"), *font); + if (const QFont *font = theme->font(QPlatformTheme::ToolButtonFont)) + fontHash->insert(QByteArrayLiteral("QToolButton"), *font); + if (const QFont *font = theme->font(QPlatformTheme::ItemViewFont)) + fontHash->insert(QByteArrayLiteral("QAbstractItemView"), *font); + if (const QFont *font = theme->font(QPlatformTheme::ListViewFont)) + fontHash->insert(QByteArrayLiteral("QListViewFont"), *font); + if (const QFont *font = theme->font(QPlatformTheme::HeaderViewFont)) { + fontHash->insert(QByteArrayLiteral("QHeaderViewFont"), *font); + fontHash->insert(QByteArrayLiteral("Q3Header"), *font); + } + if (const QFont *font = theme->font(QPlatformTheme::ListBoxFont)) + fontHash->insert(QByteArrayLiteral("QListBox"), *font); + if (const QFont *font = theme->font(QPlatformTheme::ComboMenuItemFont)) + fontHash->insert(QByteArrayLiteral("QComboMenuItemFont"), *font); + if (const QFont *font = theme->font(QPlatformTheme::ComboLineEditFont)) + fontHash->insert(QByteArrayLiteral("QComboLineEditFont"), *font); + if (const QFont *font = theme->font(QPlatformTheme::SmallFont)) + fontHash->insert(QByteArrayLiteral("QSmallFont"), *font); + if (const QFont *font = theme->font(QPlatformTheme::MiniFont)) + fontHash->insert(QByteArrayLiteral("QMiniFont"), *font); +} + #ifndef QT_NO_WHEELEVENT void QApplication::setWheelScrollLines(int lines) { @@ -416,6 +468,7 @@ QPlatformNativeInterface *QApplication::platformNativeInterface() void qt_init(QApplicationPrivate *priv, int type) { + Q_UNUSED(priv); Q_UNUSED(type); qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); @@ -423,6 +476,7 @@ void qt_init(QApplicationPrivate *priv, int type) if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) QToolTip::setPalette(*toolTipPalette); + QApplicationPrivate::initializeWidgetFontHash(); qApp->setObjectName(appName); } diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index b42fedf0be..af75d6b8aa 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -2260,7 +2260,7 @@ QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags) d->updateGeometryConstraints(); setAttribute(Qt::WA_Resized, false); d->titleBarPalette = d->desktopPalette(); - d->font = QApplication::font("QWorkspaceTitleBar"); + d->font = QApplication::font("QMdiSubWindowTitleBar"); // We don't want the menu icon by default on mac. #ifndef Q_WS_MAC if (windowIcon().isNull()) diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index f139eac275..9bb08edcce 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -1830,10 +1830,11 @@ void tst_QListView::taskQTBUG_2233_scrollHiddenItems() QStringListModel model(&view); QStringList list; for (int i = 0; i < rowCount; ++i) - list << QString::fromAscii("Item %1").arg(i); + list << QString::number(i); model.setStringList(list); view.setModel(&model); + view.setUniformItemSizes(true); view.setViewMode(QListView::ListMode); for (int i = 0; i < rowCount / 2; ++i) view.setRowHidden(2 * i, true); diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 8f187190aa..544923a1c3 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -781,10 +781,6 @@ void tst_QStyleSheetStyle::focusColors() + " did not contain background color #e8ff66, using style " + QString::fromLatin1(qApp->style()->metaObject()->className())) .toLocal8Bit().constData()); -#ifdef Q_OS_MAC - if (widget == widgets.first()) - QEXPECT_FAIL("", "Failure only for first widget, the QPushButton, see QTBUG-23686", Continue); -#endif QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)), (QString::fromLatin1(widget->metaObject()->className()) + " did not contain text color #ff0084, using style " @@ -882,8 +878,7 @@ void tst_QStyleSheetStyle::hoverColors() (QString::fromLatin1(widget->metaObject()->className()) + " did not contain background color #e8ff66").toLocal8Bit().constData()); #ifdef Q_OS_MAC - if (qobject_cast(widget) - || qobject_cast(widget)) + if (qobject_cast(widget)) QEXPECT_FAIL("", "Failure only for QPushButton and QComboBox, see QTBUG-23686", Continue); #endif QVERIFY2(testForColors(image, QColor(0xff, 0x00, 0x84)), -- cgit v1.2.3 From 5713dde8a1e6a35483134ffe9d986db66b208cf5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 7 Mar 2012 12:24:30 +0100 Subject: Fix deadlock in QPropertyAnimation Commit 1e6514a714c1f55b9cb57d2b8b65bc2305c2e2c6 changed the mutex from recursive to non-recursive, which could introduce dead lock if the animation starts other animation (This is the case in QMainWindow layouts) Change-Id: I1b149b78a802748eb24b5700fffeca0b8555f005 Reviewed-by: Friedemann Kleint --- src/corelib/animation/qpropertyanimation.cpp | 1 + .../qpropertyanimation/tst_qpropertyanimation.cpp | 45 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 83ae7bafaa..f7ba49c3cd 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -281,6 +281,7 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState, d->updateMetaProperty(); animToStop = hash.value(key, 0); hash.insert(key, this); + locker.unlock(); // update the default start value if (oldState == Stopped) { d->setDefaultStartEndValue(d->targetValue->property(d->propertyName.constData())); diff --git a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp index 534dec8160..05d1569988 100644 --- a/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/corelib/animation/qpropertyanimation/tst_qpropertyanimation.cpp @@ -123,6 +123,7 @@ private slots: void deletedInUpdateCurrentTime(); void totalDuration(); void zeroLoopCount(); + void recursiveAnimations(); }; void tst_QPropertyAnimation::initTestCase() @@ -1237,5 +1238,49 @@ void tst_QPropertyAnimation::zeroLoopCount() QCOMPARE(finishedSpy.count(), 0); } + +class RecursiveObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal x READ x WRITE setX) + Q_PROPERTY(qreal y READ y WRITE setY) +public: + RecursiveObject() : m_x(0), m_y(0) { + animation.setTargetObject(this); + animation.setPropertyName("y"); + animation.setDuration(30); + } + qreal x() const { return m_x; } + void setX(qreal x) { + m_x = x; + animation.setEndValue(x); + animation.start(); + } + qreal y() const { return m_y; } + void setY(qreal y) { m_y = y; } + + qreal m_x; + qreal m_y; + QPropertyAnimation animation; +}; + + +void tst_QPropertyAnimation::recursiveAnimations() +{ + RecursiveObject o; + QPropertyAnimation anim; + anim.setTargetObject(&o); + anim.setPropertyName("x"); + anim.setDuration(30); + + anim.setEndValue(4000); + anim.start(); + QTest::qWait(anim.duration() + o.animation.duration()); + QTRY_COMPARE(anim.state(), QAbstractAnimation::Stopped); + QTRY_COMPARE(o.animation.state(), QAbstractAnimation::Stopped); + QCOMPARE(o.y(), qreal(4000)); +} + + QTEST_MAIN(tst_QPropertyAnimation) #include "tst_qpropertyanimation.moc" -- cgit v1.2.3 From b460eca94127123b8408c7fe048d7c77446547d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Nowacki?= Date: Tue, 6 Mar 2012 16:41:47 +0100 Subject: Example build fix. buttontester.pro has to be renamed to mousebuttons.pro because it lives in mousebuttons subdirectory, to which examples/widgets/widgets.pro is pointing by SUBDIRS variable. Change-Id: I04bbd85713321337fbe8cbccfa6284f12b677279 Reviewed-by: Rick Stockton Reviewed-by: Casper van Donderen --- examples/widgets/mousebuttons/buttontester.pro | 18 ------------------ examples/widgets/mousebuttons/mousebuttons.pro | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 18 deletions(-) delete mode 100644 examples/widgets/mousebuttons/buttontester.pro create mode 100644 examples/widgets/mousebuttons/mousebuttons.pro diff --git a/examples/widgets/mousebuttons/buttontester.pro b/examples/widgets/mousebuttons/buttontester.pro deleted file mode 100644 index 823b04657e..0000000000 --- a/examples/widgets/mousebuttons/buttontester.pro +++ /dev/null @@ -1,18 +0,0 @@ -TEMPLATE = app - -TARGET = buttontester -TEMPLATE = app - -SOURCES += \ - main.cpp\ - buttontester.cpp \ - -HEADERS += \ - buttontester.h \ - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS buttontester.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons -INSTALLS += target sources -QT += core widgets diff --git a/examples/widgets/mousebuttons/mousebuttons.pro b/examples/widgets/mousebuttons/mousebuttons.pro new file mode 100644 index 0000000000..823b04657e --- /dev/null +++ b/examples/widgets/mousebuttons/mousebuttons.pro @@ -0,0 +1,18 @@ +TEMPLATE = app + +TARGET = buttontester +TEMPLATE = app + +SOURCES += \ + main.cpp\ + buttontester.cpp \ + +HEADERS += \ + buttontester.h \ + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS buttontester.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/examples/widgets/mousebuttons +INSTALLS += target sources +QT += core widgets -- cgit v1.2.3 From a6a7cabcd3b38dbd65570a23a800d7e3800a78d0 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 2 Mar 2012 15:41:51 +0100 Subject: Add QUrl formatting option "PreferLocalFile". For the readonly case (e.g. progress dialogs), where local file paths look much nicer to end users than file:/// URLs. Change-Id: I899fed27cfb73ebf565389cfd489d2d2fcbeac7c Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll --- src/corelib/io/qurl.cpp | 31 ++++++++++++++++++++++++------- src/corelib/io/qurl.h | 1 + tests/auto/corelib/io/qurl/tst_qurl.cpp | 19 ++++++++++--------- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 0659053937..9b15c1fd98 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -170,6 +170,8 @@ \value RemoveQuery The query part of the URL (following a '?' character) is removed. \value RemoveFragment + \value PreferLocalFile If the URL is a local file according to isLocalFile() + and contains no query or fragment, a local file path is returned. \value StripTrailingSlash The trailing slash is removed if one is present. Note that the case folding rules in \l{RFC 3491}{Nameprep}, which QUrl @@ -331,6 +333,7 @@ public: void clear(); QByteArray toEncoded(QUrl::FormattingOptions options = QUrl::None) const; + bool isLocalFile() const; QAtomicInt ref; @@ -3953,6 +3956,9 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const if (options==0x100) // private - see qHash(QUrl) return normalized(); + if ((options & QUrl::PreferLocalFile) && isLocalFile() && !hasQuery && !hasFragment) + return encodedPath; + QByteArray url; if (!(options & QUrl::RemoveScheme) && !scheme.isEmpty()) { @@ -5695,9 +5701,12 @@ QString QUrl::toString(FormattingOptions options) const QString url; + const QString ourPath = path(); + if ((options & QUrl::PreferLocalFile) && isLocalFile() && !d->hasQuery && !d->hasFragment) + return ourPath; + if (!(options & QUrl::RemoveScheme) && !d->scheme.isEmpty()) url += d->scheme + QLatin1Char(':'); - QString ourPath = path(); if ((options & QUrl::RemoveAuthority) != QUrl::RemoveAuthority) { bool doFileScheme = d->scheme == QLatin1String("file") && ourPath.startsWith(QLatin1Char('/')); QString tmp = d->authority(options); @@ -5733,6 +5742,7 @@ QString QUrl::toString(FormattingOptions options) const } /*! + \since 5.0 Returns a string representation of the URL. The output can be customized by passing flags with \a options. @@ -5748,13 +5758,16 @@ QString QUrl::url(FormattingOptions options) const } /*! + \since 5.0 + Returns a human-displayable string representation of the URL. The output can be customized by passing flags with \a options. The option RemovePassword is always enabled, since passwords should never be shown back to users. - The resulting QString can be passed back to a QUrl later on, - but any password that was present initially will be lost. + With the default options, the resulting QString can be passed back + to a QUrl later on, but any password that was present initially will + be lost. \sa FormattingOptions, toEncoded(), toString() */ @@ -6171,6 +6184,13 @@ QString QUrl::toLocalFile() const return tmp; } +bool QUrlPrivate::isLocalFile() const +{ + if (scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0) + return false; // not file + return true; +} + /*! \since 4.7 Returns true if this URL is pointing to a local file path. A URL is a @@ -6186,10 +6206,7 @@ bool QUrl::isLocalFile() const { if (!d) return false; if (!QURL_HASFLAG(d->stateFlags, QUrlPrivate::Parsed)) d->parse(); - - if (d->scheme.compare(QLatin1String("file"), Qt::CaseInsensitive) != 0) - return false; // not file - return true; + return d->isLocalFile(); } /*! diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 3e5c62cd7c..fc49231594 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -76,6 +76,7 @@ public: RemoveQuery = 0x40, RemoveFragment = 0x80, // 0x100: private: normalized + PreferLocalFile = 0x200, StripTrailingSlash = 0x10000 }; diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index f782b26b46..3bff330db2 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -262,9 +262,16 @@ void tst_QUrl::hashInPath() QCOMPARE(withHashInPath.path(), QString::fromLatin1("hi#mum.txt")); QCOMPARE(withHashInPath.toEncoded(), QByteArray("hi%23mum.txt")); QCOMPARE(withHashInPath.toString(), QString("hi%23mum.txt")); + QCOMPARE(withHashInPath.toDisplayString(QUrl::PreferLocalFile), QString("hi%23mum.txt")); QUrl fromHashInPath = QUrl::fromEncoded(withHashInPath.toEncoded()); QVERIFY(withHashInPath == fromHashInPath); + + const QUrl localWithHash = QUrl::fromLocalFile("/hi#mum.txt"); + QCOMPARE(localWithHash.path(), QString::fromLatin1("/hi#mum.txt")); + QCOMPARE(localWithHash.toEncoded(), QByteArray("file:///hi%23mum.txt")); + QCOMPARE(localWithHash.toString(), QString("file:///hi%23mum.txt")); + QCOMPARE(localWithHash.toDisplayString(QUrl::PreferLocalFile), QString("/hi#mum.txt")); } void tst_QUrl::unc() @@ -352,6 +359,7 @@ void tst_QUrl::setUrl() QCOMPARE(url.port(), -1); QCOMPARE(url.toString(), QString::fromLatin1("file:///")); QCOMPARE(url.toDisplayString(), QString::fromLatin1("file:///")); + QCOMPARE(url.toDisplayString(QUrl::PreferLocalFile), QString::fromLatin1("/")); } { @@ -367,6 +375,7 @@ void tst_QUrl::setUrl() QCOMPARE(url.port(), 80); QCOMPARE(url.toString(), QString::fromLatin1("http://www.foo.bar:80")); QCOMPARE(url.toDisplayString(), QString::fromLatin1("http://www.foo.bar:80")); + QCOMPARE(url.toDisplayString(QUrl::PreferLocalFile), QString::fromLatin1("http://www.foo.bar:80")); QUrl url2("//www1.foo.bar"); QCOMPARE(url.resolved(url2).toString(), QString::fromLatin1("http://www1.foo.bar")); @@ -451,15 +460,7 @@ void tst_QUrl::setUrl() QUrl url = u1; QVERIFY(url.isValid()); QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref")); - QCOMPARE(url.fragment(), QString::fromLatin1("myref")); - } - - { - QString u1 = "file:/home/dfaure/my#myref"; - QUrl url = u1; - QVERIFY(url.isValid()); - - QCOMPARE(url.toString(), QString::fromLatin1("file:///home/dfaure/my#myref")); + QCOMPARE(url.toString(QUrl::PreferLocalFile), QString::fromLatin1("file:///home/dfaure/my#myref")); QCOMPARE(url.fragment(), QString::fromLatin1("myref")); } -- cgit v1.2.3 From 24be238fccee67ad060247ad22e15b6bddd506e0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 7 Mar 2012 14:46:04 +0100 Subject: Cocoa: Implement Drag-and-Drop. Implement drag and drop support for drags originating from outside Qt. Port mime and pasteboard code from Qt 4. Use QSimpleDrag from from platform support to implement internal Qt drags. Change-Id: I5b664a95ebb00f48de2bd21c24dfb579af16123e Reviewed-by: Friedemann Kleint --- src/plugins/platforms/cocoa/cocoa.pro | 6 + src/plugins/platforms/cocoa/qcocoadrag.h | 76 ++ src/plugins/platforms/cocoa/qcocoadrag.mm | 99 +++ src/plugins/platforms/cocoa/qcocoahelpers.h | 5 + src/plugins/platforms/cocoa/qcocoahelpers.mm | 58 ++ src/plugins/platforms/cocoa/qcocoaintegration.h | 3 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 9 +- src/plugins/platforms/cocoa/qmacclipboard.h | 93 +++ src/plugins/platforms/cocoa/qmacclipboard.mm | 653 ++++++++++++++++ src/plugins/platforms/cocoa/qmacmime.h | 77 ++ src/plugins/platforms/cocoa/qmacmime.mm | 938 +++++++++++++++++++++++ src/plugins/platforms/cocoa/qnsview.h | 4 + src/plugins/platforms/cocoa/qnsview.mm | 74 ++ src/plugins/platforms/cocoa/qt_mac_p.h | 38 - 14 files changed, 2094 insertions(+), 39 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoadrag.h create mode 100644 src/plugins/platforms/cocoa/qcocoadrag.mm create mode 100644 src/plugins/platforms/cocoa/qmacclipboard.h create mode 100644 src/plugins/platforms/cocoa/qmacclipboard.mm create mode 100644 src/plugins/platforms/cocoa/qmacmime.h create mode 100644 src/plugins/platforms/cocoa/qmacmime.mm diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index ce87de2574..b953210720 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -27,6 +27,9 @@ OBJECTIVE_SOURCES += main.mm \ qcocoafiledialoghelper.mm \ qcocoafontdialoghelper.mm \ qcocoacursor.mm \ + qcocoadrag.mm \ + qmacclipboard.mm \ + qmacmime.mm \ qcocoasystemsettings.mm \ HEADERS += qcocoaintegration.h \ @@ -52,6 +55,9 @@ HEADERS += qcocoaintegration.h \ qcocoafiledialoghelper.h \ qcocoafontdialoghelper.h \ qcocoacursor.h \ + qcocoadrag.h \ + qmacclipboard.h \ + qmacmime.h \ qcocoasystemsettings.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h new file mode 100644 index 0000000000..17df54f748 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoadrag.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOADRAG_H +#define QCOCOADRAG_H + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QCocoaDrag : public QSimpleDrag +{ +public: +private: +}; + +class QCocoaDropData : public QInternalMimeData +{ +public: + QCocoaDropData(NSPasteboard *pasteboard); + ~QCocoaDropData(); +protected: + bool hasFormat_sys(const QString &mimeType) const; + QStringList formats_sys() const; + QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const; +public: + CFStringRef dropPasteboard; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm new file mode 100644 index 0000000000..c596e3fdbb --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcocoadrag.h" +#include "qmacmime.h" +#include "qmacclipboard.h" + +QT_BEGIN_NAMESPACE + +QCocoaDropData::QCocoaDropData(NSPasteboard *pasteboard) +{ + dropPasteboard = reinterpret_cast(const_cast([pasteboard name])); + CFRetain(dropPasteboard); +} + +QCocoaDropData::~QCocoaDropData() +{ + CFRelease(dropPasteboard); +} + +QStringList QCocoaDropData::formats_sys() const +{ + QStringList formats; + PasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return formats; + } + formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats(); + return formats; +} + +QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const +{ + QVariant data; + PasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return data; + } + data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type); + CFRelease(board); + return data; +} + +bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const +{ + bool has = false; + PasteboardRef board; + if (PasteboardCreate(dropPasteboard, &board) != noErr) { + qDebug("DnD: Cannot get PasteBoard!"); + return has; + } + has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType); + CFRelease(board); + return has; +} + + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 7b1247b739..3e3e8fa507 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -77,6 +77,11 @@ NSSize qt_mac_toNSSize(const QSize &qtSize); QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); +NSDragOperation qt_mac_mapDropAction(Qt::DropAction action); +NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); +Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); +Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); + // Misc void qt_mac_transformProccessToForegroundApplication(); QString qt_mac_removeMnemonics(const QString &original); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 29c505e1ab..ec4399b66c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -270,6 +270,64 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode) return i->qtKey; } +struct dndenum_mapper +{ + NSDragOperation mac_code; + Qt::DropAction qt_code; + bool Qt2Mac; +}; + +static dndenum_mapper dnd_enums[] = { + { NSDragOperationLink, Qt::LinkAction, true }, + { NSDragOperationMove, Qt::MoveAction, true }, + { NSDragOperationCopy, Qt::CopyAction, true }, + { NSDragOperationGeneric, Qt::CopyAction, false }, + { NSDragOperationEvery, Qt::ActionMask, false }, + { NSDragOperationNone, Qt::IgnoreAction, false } +}; + +NSDragOperation qt_mac_mapDropAction(Qt::DropAction action) +{ + for (int i=0; dnd_enums[i].qt_code; i++) { + if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) { + return dnd_enums[i].mac_code; + } + } + return NSDragOperationNone; +} + +NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions) +{ + NSDragOperation nsActions = NSDragOperationNone; + for (int i=0; dnd_enums[i].qt_code; i++) { + if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code)) + nsActions |= dnd_enums[i].mac_code; + } + return nsActions; +} + +Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions) +{ + Qt::DropAction action = Qt::IgnoreAction; + for (int i=0; dnd_enums[i].mac_code; i++) { + if (nsActions & dnd_enums[i].mac_code) + return dnd_enums[i].qt_code; + } + return action; +} + +Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions) +{ + Qt::DropActions actions = Qt::IgnoreAction; + for (int i=0; dnd_enums[i].mac_code; i++) { + if (nsActions & dnd_enums[i].mac_code) + actions |= dnd_enums[i].qt_code; + } + return actions; +} + + + // // Misc // diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 5493b21c34..aa0c933fab 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -46,6 +46,7 @@ #include "qcocoaautoreleasepool.h" #include "qcocoacursor.h" +#include "qcocoadrag.h" #include #include @@ -88,6 +89,7 @@ public: QPlatformNativeInterface *nativeInterface() const; QPlatformAccessibility *accessibility() const; + QPlatformDrag *drag() const; QPlatformTheme *platformTheme() const; private: @@ -98,6 +100,7 @@ private: QScopedPointer mAccessibility; QScopedPointer mPlatformTheme; QList mScreens; + QScopedPointer mCocoaDrag; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 626a7fe0f9..7921cc6ae7 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,7 @@ #include "qmenu_mac.h" #include "qcocoafiledialoghelper.h" #include "qcocoatheme.h" +#include "qmacmime.h" #include #include @@ -91,7 +92,7 @@ QCocoaIntegration::QCocoaIntegration() , mEventDispatcher(new QCocoaEventDispatcher()) , mAccessibility(new QPlatformAccessibility) , mPlatformTheme(new QCocoaTheme) - + , mCocoaDrag(new QCocoaDrag) { QCocoaAutoReleasePool pool; @@ -138,6 +139,7 @@ QCocoaIntegration::QCocoaIntegration() screenAdded(screen); } + QMacPasteboardMime::initialize(); } QCocoaIntegration::~QCocoaIntegration() @@ -198,6 +200,11 @@ QPlatformAccessibility *QCocoaIntegration::accessibility() const return mAccessibility.data(); } +QPlatformDrag *QCocoaIntegration::drag() const +{ + return mCocoaDrag.data(); +} + QPlatformTheme *QCocoaIntegration::platformTheme() const { return mPlatformTheme.data(); diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h new file mode 100644 index 0000000000..9371aca459 --- /dev/null +++ b/src/plugins/platforms/cocoa/qmacclipboard.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACCLIPBOARD_H +#define QMACCLIPBOARD_H + +#include +#include "qmacmime.h" + +#undef slots + +#import + +class QMacPasteboard +{ + struct Promise { + Promise() : itemId(0), convertor(0) { } + Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { } + int itemId, offset; + QMacPasteboardMime *convertor; + QString mime; + QVariant data; + }; + QList promises; + + PasteboardRef paste; + uchar mime_type; + mutable QPointer mime; + mutable bool mac_mime_source; + static OSStatus promiseKeeper(PasteboardRef, PasteboardItemID, CFStringRef, void *); + void clear_helper(); +public: + QMacPasteboard(PasteboardRef p, uchar mime_type=0); + QMacPasteboard(uchar mime_type); + QMacPasteboard(CFStringRef name=0, uchar mime_type=0); + ~QMacPasteboard(); + + bool hasFlavor(QString flavor) const; + bool hasOSType(int c_flavor) const; + + PasteboardRef pasteBoard() const; + QMimeData *mimeData() const; + void setMimeData(QMimeData *mime); + + QStringList formats() const; + bool hasFormat(const QString &format) const; + QVariant retrieveData(const QString &format, QVariant::Type) const; + + void clear(); + bool sync() const; +}; + +QString qt_mac_get_pasteboardString(PasteboardRef paste); + +#endif diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm new file mode 100644 index 0000000000..d5af6de69c --- /dev/null +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -0,0 +1,653 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmacclipboard.h" +#include "qclipboard.h" +#include "qapplication.h" +#include "qbitmap.h" +#include "qdatetime.h" +#include "qdebug.h" +#include "qguiapplication.h" +#include "qevent.h" +#include "qurl.h" +#include +#include +#include "qcocoahelpers.h" +#include "qmacmime.h" +#include "qcocoaautoreleasepool.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +/***************************************************************************** + QClipboard debug facilities + *****************************************************************************/ +//#define DEBUG_PASTEBOARD + +#ifndef QT_NO_CLIPBOARD + +/***************************************************************************** + QClipboard member functions for mac. + *****************************************************************************/ + +static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0}; + +static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode) +{ + Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer); + if (mode == QClipboard::Clipboard) + return qt_mac_pasteboards[0]; + else + return qt_mac_pasteboards[1]; +} + +static void qt_mac_cleanupPasteboard() { + delete qt_mac_pasteboards[0]; + delete qt_mac_pasteboards[1]; + qt_mac_pasteboards[0] = 0; + qt_mac_pasteboards[1] = 0; +} + +static bool qt_mac_updateScrap(QClipboard::Mode mode) +{ + if (!qt_mac_pasteboards[0]) { + qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP); + qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP); + qAddPostRoutine(qt_mac_cleanupPasteboard); + return true; + } + return qt_mac_pasteboard(mode)->sync(); +} + +void QClipboard::clear(Mode mode) +{ + if (!supportsMode(mode)) + return; + qt_mac_updateScrap(mode); + qt_mac_pasteboard(mode)->clear(); + setMimeData(0, mode); +} + +void QClipboard::ownerDestroyed() +{ +} + + +void QClipboard::connectNotify(const char *signal) +{ + Q_UNUSED(signal); +} + +bool QClipboard::event(QEvent *e) +{ + if (e->type() != QEvent::Clipboard) + return QObject::event(e); + + if (qt_mac_updateScrap(QClipboard::Clipboard)) { + emitChanged(QClipboard::Clipboard); + } + + if (qt_mac_updateScrap(QClipboard::FindBuffer)) { + emitChanged(QClipboard::FindBuffer); + } + + return QObject::event(e); +} + +const QMimeData *QClipboard::mimeData(Mode mode) const +{ + if (!supportsMode(mode)) + return 0; + qt_mac_updateScrap(mode); + return qt_mac_pasteboard(mode)->mimeData(); +} + +void QClipboard::setMimeData(QMimeData *src, Mode mode) +{ + if (!supportsMode(mode)) + return; + qt_mac_updateScrap(mode); + qt_mac_pasteboard(mode)->setMimeData(src); + emitChanged(mode); +} + +bool QClipboard::supportsMode(Mode mode) const +{ + return (mode == Clipboard || mode == FindBuffer); +} + +bool QClipboard::ownsMode(Mode mode) const +{ + Q_UNUSED(mode); + return false; +} + +#endif // QT_NO_CLIPBOARD + +/***************************************************************************** + QMacPasteboard code +*****************************************************************************/ + +QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt) +{ + mac_mime_source = false; + mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); + paste = p; + CFRetain(paste); +} + +QMacPasteboard::QMacPasteboard(uchar mt) +{ + mac_mime_source = false; + mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); + paste = 0; + OSStatus err = PasteboardCreate(0, &paste); + if (err == noErr) { + PasteboardSetPromiseKeeper(paste, promiseKeeper, this); + } else { + qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err); + } +} + +QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt) +{ + mac_mime_source = false; + mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL); + paste = 0; + OSStatus err = PasteboardCreate(name, &paste); + if (err == noErr) { + PasteboardSetPromiseKeeper(paste, promiseKeeper, this); + } else { + qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err); + } +} + +QMacPasteboard::~QMacPasteboard() +{ + // commit all promises for paste after exit close + for (int i = 0; i < promises.count(); ++i) { + const Promise &promise = promises.at(i); + QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime)); + promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this); + } + + if (paste) + CFRelease(paste); +} + +PasteboardRef +QMacPasteboard::pasteBoard() const +{ + return paste; +} + +OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste) +{ + QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste; + const long promise_id = (long)id; + + // Find the kept promise + const QString flavorAsQString = QCFString::toQString(flavor); + QMacPasteboard::Promise promise; + for (int i = 0; i < qpaste->promises.size(); i++){ + QMacPasteboard::Promise tmp = qpaste->promises[i]; + if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){ + promise = tmp; + break; + } + } + + if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) { + // we have promised this data, but wont be able to convert, so return null data. + // This helps in making the application/x-qt-mime-type-name hidden from normal use. + QByteArray ba; + QCFType data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size()); + PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags); + return noErr; + } + + if (!promise.itemId) { + // There was no promise that could deliver data for the + // given id and flavor. This should not happend. + qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString)); + return cantGetFlavorErr; + } + +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id, + qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset); +#endif + + QList md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString); + if (md.size() <= promise.offset) + return cantGetFlavorErr; + const QByteArray &ba = md[promise.offset]; + QCFType data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size()); + PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags); + return noErr; +} + +bool +QMacPasteboard::hasOSType(int c_flavor) const +{ + if (!paste) + return false; + + sync(); + + ItemCount cnt = 0; + if (PasteboardGetItemCount(paste, &cnt) || !cnt) + return false; + +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF, + (c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF); +#endif + for (uint index = 1; index <= cnt; ++index) { + + PasteboardItemID id; + if (PasteboardGetItemIdentifier(paste, index, &id) != noErr) + return false; + + QCFType types; + if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr) + return false; + + const int type_count = CFArrayGetCount(types); + for (int i = 0; i < type_count; ++i) { + CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i); + const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType)); + if (os_flavor == c_flavor) { +#ifdef DEBUG_PASTEBOARD + qDebug(" - Found!"); +#endif + return true; + } + } + } +#ifdef DEBUG_PASTEBOARD + qDebug(" - NotFound!"); +#endif + return false; +} + +bool +QMacPasteboard::hasFlavor(QString c_flavor) const +{ + if (!paste) + return false; + + sync(); + + ItemCount cnt = 0; + if (PasteboardGetItemCount(paste, &cnt) || !cnt) + return false; + +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor)); +#endif + for (uint index = 1; index <= cnt; ++index) { + + PasteboardItemID id; + if (PasteboardGetItemIdentifier(paste, index, &id) != noErr) + return false; + + PasteboardFlavorFlags flags; + if (PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) { +#ifdef DEBUG_PASTEBOARD + qDebug(" - Found!"); +#endif + return true; + } + } +#ifdef DEBUG_PASTEBOARD + qDebug(" - NotFound!"); +#endif + return false; +} + +class QMacPasteboardMimeSource : public QMimeData { + const QMacPasteboard *paste; +public: + QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { } + ~QMacPasteboardMimeSource() { } + virtual QStringList formats() const { return paste->formats(); } + virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); } +}; + +QMimeData +*QMacPasteboard::mimeData() const +{ + if (!mime) { + mac_mime_source = true; + mime = new QMacPasteboardMimeSource(this); + + } + return mime; +} + +class QMacMimeData : public QMimeData +{ +public: + QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); } +private: + QMacMimeData(); +}; + +void +QMacPasteboard::setMimeData(QMimeData *mime_src) +{ + if (!paste) + return; + + if (mime == mime_src || (!mime_src && mime && mac_mime_source)) + return; + mac_mime_source = false; + delete mime; + mime = mime_src; + + QList availableConverters = QMacPasteboardMime::all(mime_type); + if (mime != 0) { + clear_helper(); + QStringList formats = mime_src->formats(); + + // QMimeData sub classes reimplementing the formats() might not expose the + // temporary "application/x-qt-mime-type-name" mimetype. So check the existence + // of this mime type while doing drag and drop. + QString dummyMimeType(QLatin1String("application/x-qt-mime-type-name")); + if (!formats.contains(dummyMimeType)) { + QByteArray dummyType = mime_src->data(dummyMimeType); + if (!dummyType.isEmpty()) { + formats.append(dummyMimeType); + } + } + for (int f = 0; f < formats.size(); ++f) { + QString mimeType = formats.at(f); + for (QList::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) { + QMacPasteboardMime *c = (*it); + QString flavor(c->flavorFor(mimeType)); + if (!flavor.isEmpty()) { + QVariant mimeData = static_cast(mime_src)->variantData(mimeType); +#if 0 + //### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam + const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size(); +#else + int numItems = 1; //this is a hack but it is much faster than allowing conversion above + if (c->convertorName() == QLatin1String("FileURL")) + numItems = mime_src->urls().count(); +#endif + for (int item = 0; item < numItems; ++item) { + const int itemID = item+1; //id starts at 1 + promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item)); + PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags); +#ifdef DEBUG_PASTEBOARD + qDebug(" - adding %d %s [%s] <%s> [%d]", + itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item); +#endif + } + } + } + } + } +} + +QStringList +QMacPasteboard::formats() const +{ + if (!paste) + return QStringList(); + + sync(); + + QStringList ret; + ItemCount cnt = 0; + if (PasteboardGetItemCount(paste, &cnt) || !cnt) + return ret; + +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: Formats [%d]", (int)cnt); +#endif + for (uint index = 1; index <= cnt; ++index) { + + PasteboardItemID id; + if (PasteboardGetItemIdentifier(paste, index, &id) != noErr) + continue; + + QCFType types; + if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr) + continue; + + const int type_count = CFArrayGetCount(types); + for (int i = 0; i < type_count; ++i) { + const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i)); +#ifdef DEBUG_PASTEBOARD + qDebug(" -%s", qPrintable(QString(flavor))); +#endif + QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor); + if (!mimeType.isEmpty() && !ret.contains(mimeType)) { +#ifdef DEBUG_PASTEBOARD + qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor))); +#endif + ret << mimeType; + } + } + } + return ret; +} + +bool +QMacPasteboard::hasFormat(const QString &format) const +{ + if (!paste) + return false; + + sync(); + + ItemCount cnt = 0; + if (PasteboardGetItemCount(paste, &cnt) || !cnt) + return false; + +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: hasFormat [%s]", qPrintable(format)); +#endif + for (uint index = 1; index <= cnt; ++index) { + + PasteboardItemID id; + if (PasteboardGetItemIdentifier(paste, index, &id) != noErr) + continue; + + QCFType types; + if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr) + continue; + + const int type_count = CFArrayGetCount(types); + for (int i = 0; i < type_count; ++i) { + const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i)); +#ifdef DEBUG_PASTEBOARD + qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type); +#endif + QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor); +#ifdef DEBUG_PASTEBOARD + if (!mimeType.isEmpty()) + qDebug(" - %s", qPrintable(mimeType)); +#endif + if (mimeType == format) + return true; + } + } + return false; +} + +QVariant +QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const +{ + if (!paste) + return QVariant(); + + sync(); + + ItemCount cnt = 0; + if (PasteboardGetItemCount(paste, &cnt) || !cnt) + return QByteArray(); + +#ifdef DEBUG_PASTEBOARD + qDebug("Pasteboard: retrieveData [%s]", qPrintable(format)); +#endif + const QList mimes = QMacPasteboardMime::all(mime_type); + for (int mime = 0; mime < mimes.size(); ++mime) { + QMacPasteboardMime *c = mimes.at(mime); + QString c_flavor = c->flavorFor(format); + if (!c_flavor.isEmpty()) { + // Handle text/plain a little differently. Try handling Unicode first. + bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text") + || c_flavor == QLatin1String("public.utf8-plain-text")); + if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) { + // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped + // correctly (as '\n') in this data. The 'public.utf16-plain-text' type + // usually maps newlines to '\r' instead. + QString str = qt_mac_get_pasteboardString(paste); + if (!str.isEmpty()) + return str; + } + if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text"))) + c_flavor = QLatin1String("public.utf16-plain-text"); + + QVariant ret; + QList retList; + for (uint index = 1; index <= cnt; ++index) { + PasteboardItemID id; + if (PasteboardGetItemIdentifier(paste, index, &id) != noErr) + continue; + + QCFType types; + if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr) + continue; + + const int type_count = CFArrayGetCount(types); + for (int i = 0; i < type_count; ++i) { + CFStringRef flavor = static_cast(CFArrayGetValueAtIndex(types, i)); + if (c_flavor == QCFString::toQString(flavor)) { + QCFType macBuffer; + if (PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) { + QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer)); + if (!buffer.isEmpty()) { +#ifdef DEBUG_PASTEBOARD + qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName())); +#endif + buffer.detach(); //detach since we release the macBuffer + retList.append(buffer); + break; //skip to next element + } + } + } else { +#ifdef DEBUG_PASTEBOARD + qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName())); +#endif + } + } + } + + if (!retList.isEmpty()) { + ret = c->convertToMime(format, retList, c_flavor); + return ret; + } + } + } + return QVariant(); +} + +void QMacPasteboard::clear_helper() +{ + if (paste) + PasteboardClear(paste); + promises.clear(); +} + +void +QMacPasteboard::clear() +{ +#ifdef DEBUG_PASTEBOARD + qDebug("PasteBoard: clear!"); +#endif + clear_helper(); +} + +bool +QMacPasteboard::sync() const +{ + if (!paste) + return false; + const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified; + + if (fromGlobal) + const_cast(this)->setMimeData(0); + +#ifdef DEBUG_PASTEBOARD + if (fromGlobal) + qDebug("Pasteboard: Synchronize!"); +#endif + return fromGlobal; +} + + +QString qt_mac_get_pasteboardString(PasteboardRef paste) +{ + QCocoaAutoReleasePool pool; + NSPasteboard *pb = nil; + CFStringRef pbname; + if (PasteboardCopyName(paste, &pbname) == noErr) { + pb = [NSPasteboard pasteboardWithName:const_cast(reinterpret_cast(pbname))]; + CFRelease(pbname); + } else { + pb = [NSPasteboard generalPasteboard]; + } + if (pb) { + NSString *text = [pb stringForType:NSStringPboardType]; + if (text) + return QCFString::toQString(text); + } + return QString(); +} + + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qmacmime.h b/src/plugins/platforms/cocoa/qmacmime.h new file mode 100644 index 0000000000..842caa5f2f --- /dev/null +++ b/src/plugins/platforms/cocoa/qmacmime.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACMIME_H +#define QMACMIME_H + +#include + +#include + +class Q_GUI_EXPORT QMacPasteboardMime { + char type; +public: + enum QMacPasteboardMimeType { MIME_DND=0x01, + MIME_CLIP=0x02, + MIME_QT_CONVERTOR=0x04, + MIME_QT3_CONVERTOR=0x08, + MIME_ALL=MIME_DND|MIME_CLIP + }; + explicit QMacPasteboardMime(char); + virtual ~QMacPasteboardMime(); + + static void initialize(); + + static QList all(uchar); + static QMacPasteboardMime *convertor(uchar, const QString &mime, QString flav); + static QString flavorToMime(uchar, QString flav); + + virtual QString convertorName() = 0; + + virtual bool canConvert(const QString &mime, QString flav) = 0; + virtual QString mimeFor(QString flav) = 0; + virtual QString flavorFor(const QString &mime) = 0; + virtual QVariant convertToMime(const QString &mime, QList data, QString flav) = 0; + virtual QList convertFromMime(const QString &mime, QVariant data, QString flav) = 0; +}; + +#endif + diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm new file mode 100644 index 0000000000..db86deb91c --- /dev/null +++ b/src/plugins/platforms/cocoa/qmacmime.mm @@ -0,0 +1,938 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmacmime.h" +#include "qcocoahelpers.h" +#include "qmacclipboard.h" + +#include "qdebug.h" +#include "qpixmap.h" +#include "qimagewriter.h" +#include "qimagereader.h" +#include "qdatastream.h" +#include "qbuffer.h" +#include "qdatetime.h" +#include "qguiapplication.h" +#include "qtextcodec.h" +#include "qregexp.h" +#include "qurl.h" +#include "qmap.h" + +#include + +QT_BEGIN_NAMESPACE + +extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp + +typedef QList MimeList; +Q_GLOBAL_STATIC(MimeList, globalMimeList) + +static void cleanup_mimes() +{ + MimeList *mimes = globalMimeList(); + while (!mimes->isEmpty()) + delete mimes->takeFirst(); +} + +Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList) + +/*! + \fn void qRegisterDraggedTypes(const QStringList &types) + \relates QMacPasteboardMime + + Registers the given \a types as custom pasteboard types. + + This function should be called to enable the Drag and Drop events + for custom pasteboard types on Cocoa implementations. This is required + in addition to a QMacPasteboardMime subclass implementation. By default + drag and drop is enabled for all standard pasteboard types. + + \sa QMacPasteboardMime +*/ +Q_WIDGETS_EXPORT void qRegisterDraggedTypes(const QStringList &types) +{ + (*globalDraggedTypesList()) += types; +} + +const QStringList& qEnabledDraggedTypes() +{ + return (*globalDraggedTypesList()); +} + + +/***************************************************************************** + QDnD debug facilities + *****************************************************************************/ +//#define DEBUG_MIME_MAPS + +//functions +extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp +extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp + +ScrapFlavorType qt_mac_mime_type = 'CUTE'; +CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker"); + +/*! + \class QMacPasteboardMime + \brief The QMacPasteboardMime class converts between a MIME type and a + \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform + Type Identifier (UTI)} format. + \since 4.2 + + \ingroup draganddrop + \inmodule QtWidgets + + Qt's drag and drop and clipboard facilities use the MIME + standard. On X11, this maps trivially to the Xdnd protocol. On + Mac, although some applications use MIME to describe clipboard + contents, it is more common to use Apple's UTI format. + + QMacPasteboardMime's role is to bridge the gap between MIME and UTI; + By subclasses this class, one can extend Qt's drag and drop + and clipboard handling to convert to and from unsupported, or proprietary, UTI formats. + + A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation. + + Qt has predefined support for the following UTIs: + \list + \i public.utf8-plain-text - converts to "text/plain" + \i public.utf16-plain-text - converts to "text/plain" + \i public.html - converts to "text/html" + \i public.url - converts to "text/uri-list" + \i public.file-url - converts to "text/uri-list" + \i public.tiff - converts to "application/x-qt-image" + \i public.vcard - converts to "text/plain" + \i com.apple.traditional-mac-plain-text - converts to "text/plain" + \i com.apple.pict - converts to "application/x-qt-image" + \endlist + + When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to + find an instance that can convert to, or from, a specific MIME type. It will do this by calling + canConvert() on each instance, starting with (and choosing) the last created instance first. + The actual conversions will be done by using convertToMime() and convertFromMime(). + + \note The API uses the term "flavor" in some cases. This is for backwards + compatibility reasons, and should now be understood as UTIs. +*/ + +/*! \enum QMacPasteboardMime::QMacPasteboardMimeType + \internal +*/ + +/*! + Constructs a new conversion object of type \a t, adding it to the + globally accessed list of available convertors. +*/ +QMacPasteboardMime::QMacPasteboardMime(char t) : type(t) +{ + globalMimeList()->append(this); +} + +/*! + Destroys a conversion object, removing it from the global + list of available convertors. +*/ +QMacPasteboardMime::~QMacPasteboardMime() +{ + if (!QGuiApplication::closingDown()) + globalMimeList()->removeAll(this); +} + +class QMacPasteboardMimeAny : public QMacPasteboardMime { +private: + +public: + QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) { + } + ~QMacPasteboardMimeAny() { + } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeAny::convertorName() +{ + return QLatin1String("Any-Mime"); +} + +QString QMacPasteboardMimeAny::flavorFor(const QString &mime) +{ + // do not handle the mime type name in the drag pasteboard + if (mime == QLatin1String("application/x-qt-mime-type-name")) + return QString(); + QString ret = QLatin1String("com.trolltech.anymime.") + mime; + return ret.replace(QLatin1Char('/'), QLatin1String("--")); +} + +QString QMacPasteboardMimeAny::mimeFor(QString flav) +{ + const QString any_prefix = QLatin1String("com.trolltech.anymime."); + if (flav.size() > any_prefix.length() && flav.startsWith(any_prefix)) + return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/")); + return QString(); +} + +bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav) +{ + return mimeFor(flav) == mime; +} + +QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList data, QString) +{ + if (data.count() > 1) + qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data"); + QVariant ret; + if (mime == QLatin1String("text/plain")) + ret = QString::fromUtf8(data.first()); + else + ret = data.first(); + return ret; +} + +QList QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString) +{ + QList ret; + if (mime == QLatin1String("text/plain")) + ret.append(data.toString().toUtf8()); + else + ret.append(data.toByteArray()); + return ret; +} + +class QMacPasteboardMimeTypeName : public QMacPasteboardMime { +private: + +public: + QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) { + } + ~QMacPasteboardMimeTypeName() { + } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeTypeName::convertorName() +{ + return QLatin1String("Qt-Mime-Type"); +} + +QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime) +{ + if (mime == QLatin1String("application/x-qt-mime-type-name")) + return QLatin1String("com.trolltech.qt.MimeTypeName"); + return QString(); +} + +QString QMacPasteboardMimeTypeName::mimeFor(QString) +{ + return QString(); +} + +bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString) +{ + return false; +} + +QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList, QString) +{ + QVariant ret; + return ret; +} + +QList QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString) +{ + QList ret; + ret.append(QString("x-qt-mime-type-name").toUtf8()); + return ret; +} + +class QMacPasteboardMimePlainText : public QMacPasteboardMime { +public: + QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimePlainText::convertorName() +{ + return QLatin1String("PlainText"); +} + +QString QMacPasteboardMimePlainText::flavorFor(const QString &mime) +{ + if (mime == QLatin1String("text/plain")) + return QLatin1String("com.apple.traditional-mac-plain-text"); + return QString(); +} + +QString QMacPasteboardMimePlainText::mimeFor(QString flav) +{ + if (flav == QLatin1String("com.apple.traditional-mac-plain-text")) + return QLatin1String("text/plain"); + return QString(); +} + +bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav) +{ + return flavorFor(mime) == flav; +} + +QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList data, QString flavor) +{ + if (data.count() > 1) + qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data"); + const QByteArray &firstData = data.first(); + QVariant ret; + if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) { + QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(firstData.constData()), + firstData.size(), CFStringGetSystemEncoding(), false)); + ret = QString(str); + } else { + qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); + } + return ret; +} + +QList QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor) +{ + QList ret; + QString string = data.toString(); + if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) + ret.append(string.toLatin1()); + return ret; +} + +class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime { +public: + QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeUnicodeText::convertorName() +{ + return QLatin1String("UnicodeText"); +} + +QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime) +{ + if (mime == QLatin1String("text/plain")) + return QLatin1String("public.utf16-plain-text"); + int i = mime.indexOf(QLatin1String("charset=")); + if (i >= 0) { + QString cs(mime.mid(i+8).toLower()); + i = cs.indexOf(QLatin1Char(';')); + if (i>=0) + cs = cs.left(i); + if (cs == QLatin1String("system")) + return QLatin1String("public.utf8-plain-text"); + else if (cs == QLatin1String("iso-10646-ucs-2") + || cs == QLatin1String("utf16")) + return QLatin1String("public.utf16-plain-text"); + } + return QString(); +} + +QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text")) + return QLatin1String("text/plain"); + return QString(); +} + +bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav) +{ + return flavorFor(mime) == flav; +} + +QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList data, QString flavor) +{ + if (data.count() > 1) + qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data"); + const QByteArray &firstData = data.first(); + // I can only handle two types (system and unicode) so deal with them that way + QVariant ret; + if (flavor == QLatin1String("public.utf8-plain-text")) { + QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast(firstData.constData()), + firstData.size(), CFStringGetSystemEncoding(), false)); + ret = QString(str); + } else if (flavor == QLatin1String("public.utf16-plain-text")) { + ret = QString(reinterpret_cast(firstData.constData()), + firstData.size() / sizeof(QChar)); + } else { + qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype)); + } + return ret; +} + +QList QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor) +{ + QList ret; + QString string = data.toString(); + if (flavor == QLatin1String("public.utf8-plain-text")) + ret.append(string.toUtf8()); + else if (flavor == QLatin1String("public.utf16-plain-text")) + ret.append(QByteArray((char*)string.utf16(), string.length()*2)); + return ret; +} + +class QMacPasteboardMimeHTMLText : public QMacPasteboardMime { +public: + QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeHTMLText::convertorName() +{ + return QLatin1String("HTML"); +} + +QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime) +{ + if (mime == QLatin1String("text/html")) + return QLatin1String("public.html"); + return QString(); +} + +QString QMacPasteboardMimeHTMLText::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.html")) + return QLatin1String("text/html"); + return QString(); +} + +bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav) +{ + return flavorFor(mime) == flav; +} + +QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList data, QString flavor) +{ + if (!canConvert(mimeType, flavor)) + return QVariant(); + if (data.count() > 1) + qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data"); + return data.first(); +} + +QList QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor) +{ + QList ret; + if (!canConvert(mime, flavor)) + return ret; + ret.append(data.toByteArray()); + return ret; +} + +class QMacPasteboardMimeTiff : public QMacPasteboardMime { +public: + QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeTiff::convertorName() +{ + return QLatin1String("Tiff"); +} + +QString QMacPasteboardMimeTiff::flavorFor(const QString &mime) +{ + if (mime.startsWith(QLatin1String("application/x-qt-image"))) + return QLatin1String("public.tiff"); + return QString(); +} + +QString QMacPasteboardMimeTiff::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.tiff")) + return QLatin1String("application/x-qt-image"); + return QString(); +} + +bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav) +{ + return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image"); +} + +QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList data, QString flav) +{ + if (data.count() > 1) + qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data"); + QVariant ret; + if (!canConvert(mime, flav)) + return ret; + const QByteArray &a = data.first(); + QCFType image; + QCFType tiffData = CFDataCreateWithBytesNoCopy(0, + reinterpret_cast(a.constData()), + a.size(), kCFAllocatorNull); + QCFType imageSource = CGImageSourceCreateWithData(tiffData, 0); + image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0); + + // ### TODO (msorvig) QPixmap conversion + //if (image != 0) + // ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage()); + return ret; +} + +QList QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav) +{ + QList ret; + if (!canConvert(mime, flav)) + return ret; + + QImage img = qvariant_cast(variant); + QCFType cgimage = qt_mac_image_to_cgimage(img); + + QCFType data = CFDataCreateMutable(0, 0); + QCFType imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0); + if (imageDestination != 0) { + CFTypeRef keys[2]; + QCFType values[2]; + QCFType options; + keys[0] = kCGImagePropertyPixelWidth; + keys[1] = kCGImagePropertyPixelHeight; + int width = img.width(); + int height = img.height(); + values[0] = CFNumberCreate(0, kCFNumberIntType, &width); + values[1] = CFNumberCreate(0, kCFNumberIntType, &height); + options = CFDictionaryCreate(0, reinterpret_cast(keys), + reinterpret_cast(values), 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CGImageDestinationAddImage(imageDestination, cgimage, options); + CGImageDestinationFinalize(imageDestination); + } + QByteArray ar(CFDataGetLength(data), 0); + CFDataGetBytes(data, + CFRangeMake(0, ar.size()), + reinterpret_cast(ar.data())); + ret.append(ar); + return ret; +} + + +class QMacPasteboardMimeFileUri : public QMacPasteboardMime { +public: + QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeFileUri::convertorName() +{ + return QLatin1String("FileURL"); +} + +QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime) +{ + if (mime == QLatin1String("text/uri-list")) + return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)); + return QString(); +} + +QString QMacPasteboardMimeFileUri::mimeFor(QString flav) +{ + if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0))) + return QLatin1String("text/uri-list"); + return QString(); +} + +bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav) +{ + return mime == QLatin1String("text/uri-list") + && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)); +} + +QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList data, QString flav) +{ + if (!canConvert(mime, flav)) + return QVariant(); + QList ret; + for (int i = 0; i < data.size(); ++i) { + QUrl url = QUrl::fromEncoded(data.at(i)); + if (url.host().toLower() == QLatin1String("localhost")) + url.setHost(QString()); + url.setPath(url.path().normalized(QString::NormalizationForm_C)); + ret.append(url); + } + return QVariant(ret); +} + +QList QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav) +{ + QList ret; + if (!canConvert(mime, flav)) + return ret; + QList urls = data.toList(); + for (int i = 0; i < urls.size(); ++i) { + QUrl url = urls.at(i).toUrl(); + if (url.scheme().isEmpty()) + url.setScheme(QLatin1String("file")); + if (url.scheme().toLower() == QLatin1String("file")) { + if (url.host().isEmpty()) + url.setHost(QLatin1String("localhost")); + url.setPath(url.path().normalized(QString::NormalizationForm_D)); + } + ret.append(url.toEncoded()); + } + return ret; +} + +class QMacPasteboardMimeUrl : public QMacPasteboardMime { +public: + QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { } + QString convertorName(); + + QString flavorFor(const QString &mime); + QString mimeFor(QString flav); + bool canConvert(const QString &mime, QString flav); + QVariant convertToMime(const QString &mime, QList data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeUrl::convertorName() +{ + return QLatin1String("URL"); +} + +QString QMacPasteboardMimeUrl::flavorFor(const QString &mime) +{ + if (mime.startsWith(QLatin1String("text/uri-list"))) + return QLatin1String("public.url"); + return QString(); +} + +QString QMacPasteboardMimeUrl::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.url")) + return QLatin1String("text/uri-list"); + return QString(); +} + +bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav) +{ + return flav == QLatin1String("public.url") + && mime == QLatin1String("text/uri-list"); +} + +QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList data, QString flav) +{ + if (!canConvert(mime, flav)) + return QVariant(); + + QList ret; + for (int i=0; i QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav) +{ + QList ret; + if (!canConvert(mime, flav)) + return ret; + + QList urls = data.toList(); + for (int i=0; i data, QString flav); + QList convertFromMime(const QString &mime, QVariant data, QString flav); +}; + +QString QMacPasteboardMimeVCard::convertorName() +{ + return QString("VCard"); +} + +bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav) +{ + return mimeFor(flav) == mime; +} + +QString QMacPasteboardMimeVCard::flavorFor(const QString &mime) +{ + if (mime.startsWith(QLatin1String("text/plain"))) + return QLatin1String("public.vcard"); + return QString(); +} + +QString QMacPasteboardMimeVCard::mimeFor(QString flav) +{ + if (flav == QLatin1String("public.vcard")) + return QLatin1String("text/plain"); + return QString(); +} + +QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList data, QString) +{ + QByteArray cards; + if (mime == QLatin1String("text/plain")) { + for (int i=0; i QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString) +{ + QList ret; + if (mime == QLatin1String("text/plain")) + ret.append(data.toString().toUtf8()); + return ret; +} + + +/*! + \internal + + This is an internal function. +*/ +void QMacPasteboardMime::initialize() +{ + if (globalMimeList()->isEmpty()) { + qAddPostRoutine(cleanup_mimes); + + //standard types that we wrap + new QMacPasteboardMimeTiff; + new QMacPasteboardMimeUnicodeText; + new QMacPasteboardMimePlainText; + new QMacPasteboardMimeHTMLText; + new QMacPasteboardMimeFileUri; + new QMacPasteboardMimeUrl; + new QMacPasteboardMimeTypeName; + new QMacPasteboardMimeVCard; + //make sure our "non-standard" types are always last! --Sam + new QMacPasteboardMimeAny; + } +} + +/*! + Returns the most-recently created QMacPasteboardMime of type \a t that can convert + between the \a mime and \a flav formats. Returns 0 if no such convertor + exists. +*/ +QMacPasteboardMime* +QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav) +{ + MimeList *mimes = globalMimeList(); + for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { +#ifdef DEBUG_MIME_MAPS + qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]", + (*it)->convertorName().toLatin1().constData(), + (*it)->type & t, mime.toLatin1().constData(), + flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF, + (*it)->canConvert(mime,flav)); + for (int i = 0; i < (*it)->countFlavors(); ++i) { + int f = (*it)->flavor(i); + qDebug(" %d) %d[%c%c%c%c] [%s]", i, f, + (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF, + (*it)->convertorName().toLatin1().constData()); + } +#endif + if (((*it)->type & t) && (*it)->canConvert(mime, flav)) + return (*it); + } + return 0; +} +/*! + Returns a MIME type of type \a t for \a flav, or 0 if none exists. +*/ +QString QMacPasteboardMime::flavorToMime(uchar t, QString flav) +{ + MimeList *mimes = globalMimeList(); + for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { +#ifdef DEBUG_MIME_MAPS + qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]", + (*it)->convertorName().toLatin1().constData(), + (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF, + (*it)->mimeFor(flav).toLatin1().constData()); + +#endif + if ((*it)->type & t) { + QString mimeType = (*it)->mimeFor(flav); + if (!mimeType.isNull()) + return mimeType; + } + } + return QString(); +} + +/*! + Returns a list of all currently defined QMacPasteboardMime objects of type \a t. +*/ +QList QMacPasteboardMime::all(uchar t) +{ + MimeList ret; + MimeList *mimes = globalMimeList(); + for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) { + if ((*it)->type & t) + ret.append((*it)); + } + return ret; +} + + +/*! + \fn QString QMacPasteboardMime::convertorName() + + Returns a name for the convertor. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav) + + Returns true if the convertor can convert (both ways) between + \a mime and \a flav; otherwise returns false. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QString QMacPasteboardMime::mimeFor(QString flav) + + Returns the MIME UTI used for Mac flavor \a flav, or 0 if this + convertor does not support \a flav. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QString QMacPasteboardMime::flavorFor(const QString &mime) + + Returns the Mac UTI used for MIME type \a mime, or 0 if this + convertor does not support \a mime. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList data, QString flav) + + Returns \a data converted from Mac UTI \a flav to MIME type \a + mime. + + Note that Mac flavors must all be self-terminating. The input \a + data may contain trailing data. + + All subclasses must reimplement this pure virtual function. +*/ + +/*! + \fn QList QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav) + + Returns \a data converted from MIME type \a mime + to Mac UTI \a flav. + + Note that Mac flavors must all be self-terminating. The return + value may contain trailing data. + + All subclasses must reimplement this pure virtual function. +*/ + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index c61ff2bd02..1a1a1cd3b9 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -57,6 +57,7 @@ QT_END_NAMESPACE QCocoaWindow *m_platformWindow; Qt::MouseButtons m_buttons; QAccessibleInterface *m_accessibleRoot; + QStringList *currentCustomDragTypes; } - (id)init; @@ -91,6 +92,9 @@ QT_END_NAMESPACE - (void)keyDown:(NSEvent *)theEvent; - (void)keyUp:(NSEvent *)theEvent; +- (void)registerDragTypes; +- (NSDragOperation)handleDrag:(id )sender; + @end #endif //QNSVIEW_H diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a43b3fe893..9ed3332ba5 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -46,7 +46,9 @@ #include "qnsview.h" #include "qcocoawindow.h" #include "qcocoahelpers.h" +#include "qcocoaautoreleasepool.h" #include "qmultitouch_mac_p.h" +#include "qcocoadrag.h" #include #include @@ -72,6 +74,7 @@ static QTouchDevice *touchDevice = 0; m_cgImage = 0; m_window = 0; m_buttons = Qt::NoButton; + currentCustomDragTypes = 0; if (!touchDevice) { touchDevice = new QTouchDevice; touchDevice->setType(QTouchDevice::TouchPad); @@ -109,6 +112,7 @@ static QTouchDevice *touchDevice = 0; m_accessibleRoot = window->accessibleRoot(); #endif + [self registerDragTypes]; [self setPostsFrameChangedNotifications : YES]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateGeometry) @@ -471,4 +475,74 @@ static QTouchDevice *touchDevice = 0; [self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)]; } +-(void)registerDragTypes +{ + QCocoaAutoReleasePool pool; + // ### Custom types disabled. + QStringList customTypes; // = qEnabledDraggedTypes(); + if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) { + if (currentCustomDragTypes == 0) + currentCustomDragTypes = new QStringList(); + *currentCustomDragTypes = customTypes; + const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName"; + NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType, + NSFilenamesPboardType, NSStringPboardType, + NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType, + NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType, + NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType, + NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType, + NSURLPboardType, NSPDFPboardType, NSVCardPboardType, + NSFilesPromisePboardType, NSInkTextPboardType, + NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil]; + // Add custom types supported by the application. + for (int i = 0; i < customTypes.size(); i++) { + [supportedTypes addObject:QCFString::toNSString(customTypes[i])]; + } + [self registerForDraggedTypes:supportedTypes]; + } +} + +- (NSDragOperation)draggingEntered:(id )sender +{ + return [self handleDrag : sender]; +} + +- (NSDragOperation)draggingUpdated:(id )sender +{ + return [self handleDrag : sender]; +} + +// Sends drag update to Qt, return the action +- (NSDragOperation)handleDrag:(id )sender +{ + NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; + QPoint qt_windowPoint(windowPoint.x, windowPoint.y); + Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); + QCocoaDropData mimeData([sender draggingPasteboard]); + + QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_window, &mimeData, qt_windowPoint, qtAllowed); + return qt_mac_mapDropAction(response.acceptedAction()); +} + +- (void)draggingExited:(id )sender +{ + NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; + QPoint qt_windowPoint(windowPoint.x, windowPoint.y); + + // Send 0 mime data to indicate drag exit + QWindowSystemInterface::handleDrag(m_window, 0 ,qt_windowPoint, Qt::IgnoreAction); +} + +// called on drop, send the drop to Qt and return if it was accepted. +- (BOOL)performDragOperation:(id )sender +{ + NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; + QPoint qt_windowPoint(windowPoint.x, windowPoint.y); + Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); + QCocoaDropData mimeData([sender draggingPasteboard]); + + QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_window, &mimeData, qt_windowPoint, qtAllowed); + return response.isAccepted(); +} + @end diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h index 8e94880c5a..b75e6e2bcb 100644 --- a/src/plugins/platforms/cocoa/qt_mac_p.h +++ b/src/plugins/platforms/cocoa/qt_mac_p.h @@ -196,44 +196,6 @@ public: class QMacPasteboardMime; class QMimeData; -class QMacPasteboard -{ - struct Promise { - Promise() : itemId(0), convertor(0) { } - Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { } - int itemId, offset; - QMacPasteboardMime *convertor; - QString mime; - QVariant data; - }; - QList promises; - - OSPasteboardRef paste; - uchar mime_type; - mutable QPointer mime; - mutable bool mac_mime_source; - static OSStatus promiseKeeper(OSPasteboardRef, PasteboardItemID, CFStringRef, void *); - void clear_helper(); -public: - QMacPasteboard(OSPasteboardRef p, uchar mime_type=0); - QMacPasteboard(uchar mime_type); - QMacPasteboard(CFStringRef name=0, uchar mime_type=0); - ~QMacPasteboard(); - - bool hasFlavor(QString flavor) const; - bool hasOSType(int c_flavor) const; - - OSPasteboardRef pasteBoard() const; - QMimeData *mimeData() const; - void setMimeData(QMimeData *mime); - - QStringList formats() const; - bool hasFormat(const QString &format) const; - QVariant retrieveData(const QString &format, QVariant::Type) const; - - void clear(); - bool sync() const; -}; extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp -- cgit v1.2.3 From 83d113feb01be72f9a0f1714b69541e7ebc7c4ca Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 7 Mar 2012 13:31:30 +0200 Subject: Windows: Fix override cursor logic Fixed a logic error that prevented override cursors being applied in Windows plugin. The logic for override cursor handling is already in crossplatform code, so no need to do extra checks in plugin. Task-number: QTBUG-24657 Change-Id: Ied9b36b57f22607ef5bb5c30f2926b0053eebca5 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index b2ebe06a58..f5cac4d4f0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1309,16 +1309,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const } /*! - \brief Applies to cursor property set on the window to the global cursor - unless there is an override cursor. + \brief Applies to cursor property set on the window to the global cursor. \sa QWindowsCursor */ void QWindowsWindow::applyCursor() { - if (!QGuiApplication::overrideCursor()) - SetCursor(m_cursor.handle()); + SetCursor(m_cursor.handle()); } void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) -- cgit v1.2.3 From 7bc576771de0b3c96905a6d11a75a01917334dc9 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 6 Mar 2012 13:58:31 +0200 Subject: Fix sending simulated keyboard events to popup widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Popup widgets steal the keyboard grab stealthily without it being visible via QWidget::keyboardGrabber(). To more accurately simulate a real keyboard event, prioritize sending simulated keyboard events to the active popup widget over QGuiApplication::focusWindow(). Task-number: QTBUG-24326 Change-Id: Id7a75c613d934e24657b521f1684ce7cce92556a Reviewed-by: Morten Johan Sørvig Reviewed-by: Friedemann Kleint Reviewed-by: Jason McDonald --- src/testlib/qtestkeyboard.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 897c732f45..5625bd606c 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -191,18 +191,20 @@ namespace QTest if (!widget) widget = QWidget::keyboardGrabber(); + if (!widget) { + // Popup widgets stealthily steal the keyboard grab + if (QWidget *apw = QApplication::activePopupWidget()) + widget = apw->focusWidget() ? apw->focusWidget() : apw; + } if (!widget) { QWindow *window = QGuiApplication::focusWindow(); if (window) { sendKeyEvent(action, window, code, text, modifier, delay); return; } - - if (QWidget *apw = QApplication::activePopupWidget()) - widget = apw->focusWidget() ? apw->focusWidget() : apw; - else - widget = QApplication::focusWidget(); } + if (!widget) + widget = QApplication::focusWidget(); if (!widget) widget = QApplication::activeWindow(); -- cgit v1.2.3 From 3bb902495291c50a2f06e8e03a62a647db3e5cd4 Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Tue, 6 Mar 2012 16:44:52 -0800 Subject: QWidget: fix wrong mouse behavior Widgets will receive extra mouse press events when double clicked. This is a side effect of change Id Ief6af12c666b23e544da4a68cb835cd577265469 which has partially fixed the folowing bug. Task-number:QTBUG-24649 Change-Id: I030ac6ba641050d40ac8989720a1c261ab15f849 Reviewed-by: Laszlo Agocs Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 5eee5752cc..bf864503a4 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -8390,7 +8390,6 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event) void QWidget::mouseDoubleClickEvent(QMouseEvent *event) { - mousePressEvent(event); // try mouse press event } #ifndef QT_NO_WHEELEVENT -- cgit v1.2.3 From 55701b7de9d309a2492c637dd7aaf85ed569f1eb Mon Sep 17 00:00:00 2001 From: Rafael Roquetto Date: Wed, 7 Mar 2012 09:10:10 +0100 Subject: Fixing iconv test to match new mkspec name Fixed iconv.pro file to follow the qnx mkspec renaming from blackberry- to qnx- Change-Id: I91e0e2495d0ec70c6ffec3e3e83eb8712805b3aa Reviewed-by: Lars Knoll --- config.tests/unix/iconv/iconv.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.tests/unix/iconv/iconv.pro b/config.tests/unix/iconv/iconv.pro index ec573ce590..876c6f3589 100644 --- a/config.tests/unix/iconv/iconv.pro +++ b/config.tests/unix/iconv/iconv.pro @@ -1,3 +1,3 @@ SOURCES = iconv.cpp CONFIG -= qt dylib app_bundle -mac|win32-g++*|blackberry-*-qcc:LIBS += -liconv +mac|win32-g++*|qnx-*-qcc:LIBS += -liconv -- cgit v1.2.3 From aee8f7d81eaec36e7d406607644f8fce294f7e21 Mon Sep 17 00:00:00 2001 From: Girish Ramakrishnan Date: Tue, 6 Mar 2012 18:51:41 -0800 Subject: Remove references to missing tests 17ddce4692b31af4374b28cd40b9f25e8ed629cd removed the endian test. 90a5492fb01ec3bc10c18c5a0acd38d6ed845a6d removed the ipv6 test. largefile and nix are long dead. Change-Id: If8e5d4f0546e30778b82ee99f662cb9ed3aefacb Reviewed-by: Oswald Buddenhagen --- qtbase.pro | 4 ---- 1 file changed, 4 deletions(-) diff --git a/qtbase.pro b/qtbase.pro index 01a5aa33dc..9290d5adcd 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -39,9 +39,6 @@ confclean.depends += clean confclean.commands = unix { confclean.commands += (cd config.tests/unix/stl && $(MAKE) distclean); \ - (cd config.tests/unix/endian && $(MAKE) distclean); \ - (cd config.tests/unix/ipv6 && $(MAKE) distclean); \ - (cd config.tests/unix/largefile && $(MAKE) distclean); \ (cd config.tests/unix/ptrsize && $(MAKE) distclean); \ (cd config.tests/x11/notype && $(MAKE) distclean); \ (cd config.tests/unix/getaddrinfo && $(MAKE) distclean); \ @@ -50,7 +47,6 @@ unix { (cd config.tests/unix/mysql && $(MAKE) distclean); \ (cd config.tests/unix/mysql_r && $(MAKE) distclean); \ (cd config.tests/unix/nis && $(MAKE) distclean); \ - (cd config.tests/unix/nix && $(MAKE) distclean); \ (cd config.tests/unix/iodbc && $(MAKE) distclean); \ (cd config.tests/unix/odbc && $(MAKE) distclean); \ (cd config.tests/unix/oci && $(MAKE) distclean); \ -- cgit v1.2.3 From eb709333989a7e3d8eb662a0e167ac81ca19d882 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 22 Feb 2012 03:33:00 +0000 Subject: QRegularExpression: add optimizations autotest Exporting the counter that controls the optimization of a compiled pattern lets us to forcibly optimize all patterns. Therefore, two tests are now run: one with default optimization values and another one which always optimizes the pattern. The counter itself was renamed with a qt_ prefix and put inside the Qt compilation namespace (thanks to rohanpm for pointing it out). Change-Id: I56602433d37adc127772b2d0d2cdaf2e49d43c71 Reviewed-by: Rohan McGovern Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 14 ++-- .../corelib/tools/qregularexpression/.gitignore | 3 +- .../alwaysoptimize/alwaysoptimize.pro | 7 ++ .../tst_qregularexpression_alwaysoptimize.cpp | 64 ++++++++++++++++++ .../defaultoptimize/defaultoptimize.pro | 7 ++ .../tst_qregularexpression_defaultoptimize.cpp | 52 +++++++++++++++ .../qregularexpression/qregularexpression.pro | 7 +- .../qregularexpression/tst_qregularexpression.cpp | 40 +---------- .../qregularexpression/tst_qregularexpression.h | 77 ++++++++++++++++++++++ 9 files changed, 222 insertions(+), 49 deletions(-) create mode 100644 tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro create mode 100644 tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp create mode 100644 tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro create mode 100644 tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp create mode 100644 tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 0252a30c89..0fa7d6459e 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -50,9 +50,6 @@ #include -// after how many usages we optimize the regexp -static const unsigned int OPTIMIZE_AFTER_USE_COUNT = 10; - QT_BEGIN_NAMESPACE /*! @@ -726,6 +723,13 @@ QT_BEGIN_NAMESPACE contain any metacharacter that anchors the match at that point. */ +// after how many usages we optimize the regexp +#ifdef QT_BUILD_INTERNAL +Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = 10; +#else +static const unsigned int qt_qregularexpression_optimize_after_use_count = 10; +#endif // QT_BUILD_INTERNAL + /*! \internal */ @@ -1012,7 +1016,7 @@ static bool isJitEnabled() setting the studyData member variable to the result of the study. It gets called by doMatch() every time a match is performed. As of now, the optimizations on the pattern are performed after a certain number of usages - (i.e. the OPTIMIZE_AFTER_USE_COUNT constant). + (i.e. the qt_qregularexpression_optimize_after_use_count constant). Notice that although the method is protected by a mutex, one thread may invoke this function and return immediately (i.e. not study the pattern, @@ -1028,7 +1032,7 @@ pcre16_extra *QRegularExpressionPrivate::optimizePattern() QMutexLocker lock(&mutex); - if (studyData || (++usedCount != OPTIMIZE_AFTER_USE_COUNT)) + if (studyData || (++usedCount != qt_qregularexpression_optimize_after_use_count)) return studyData; static const bool enableJit = isJitEnabled(); diff --git a/tests/auto/corelib/tools/qregularexpression/.gitignore b/tests/auto/corelib/tools/qregularexpression/.gitignore index 4a224d26fc..c9249e090e 100644 --- a/tests/auto/corelib/tools/qregularexpression/.gitignore +++ b/tests/auto/corelib/tools/qregularexpression/.gitignore @@ -1 +1,2 @@ -tst_qregularexpression +tst_qregularexpression_alwaysoptimize +tst_qregularexpression_defaultoptimize diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro new file mode 100644 index 0000000000..f48b1ee96a --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/alwaysoptimize.pro @@ -0,0 +1,7 @@ +CONFIG += testcase parallel_test +TARGET = tst_qregularexpression_alwaysoptimize +QT = core testlib +HEADERS = ../tst_qregularexpression.h +SOURCES = \ + tst_qregularexpression_alwaysoptimize.cpp \ + ../tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp new file mode 100644 index 0000000000..9190f183a1 --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/alwaysoptimize/tst_qregularexpression_alwaysoptimize.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "../tst_qregularexpression.h" + +class tst_QRegularExpression_AlwaysOptimize : public tst_QRegularExpression +{ + Q_OBJECT + +private slots: + void initTestCase(); +}; + +QT_BEGIN_NAMESPACE +extern Q_CORE_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count; // from qregularexpression.cpp +QT_END_NAMESPACE + +void tst_QRegularExpression_AlwaysOptimize::initTestCase() +{ + qt_qregularexpression_optimize_after_use_count = 1; +} + +QTEST_APPLESS_MAIN(tst_QRegularExpression_AlwaysOptimize) + +#include "tst_qregularexpression_alwaysoptimize.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro new file mode 100644 index 0000000000..dd1a90cfbc --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/defaultoptimize.pro @@ -0,0 +1,7 @@ +CONFIG += testcase parallel_test +TARGET = tst_qregularexpression_defaultoptimize +QT = core testlib +HEADERS = ../tst_qregularexpression.h +SOURCES = \ + tst_qregularexpression_defaultoptimize.cpp \ + ../tst_qregularexpression.cpp diff --git a/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp new file mode 100644 index 0000000000..d0b5bee4b7 --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/defaultoptimize/tst_qregularexpression_defaultoptimize.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "../tst_qregularexpression.h" + +class tst_QRegularExpression_DefaultOptimize : public tst_QRegularExpression +{ + Q_OBJECT +}; + +QTEST_APPLESS_MAIN(tst_QRegularExpression_DefaultOptimize) + +#include "tst_qregularexpression_defaultoptimize.moc" diff --git a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro index bce6643be6..0cae10112f 100644 --- a/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro +++ b/tests/auto/corelib/tools/qregularexpression/qregularexpression.pro @@ -1,4 +1,3 @@ -CONFIG += testcase parallel_test -TARGET = tst_qregularexpression -QT = core testlib -SOURCES = tst_qregularexpression.cpp +TEMPLATE = subdirs +SUBDIRS = defaultoptimize +contains(QT_CONFIG,private_tests):SUBDIRS += alwaysoptimize diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 238d8626c3..72157c0536 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -40,45 +40,12 @@ ****************************************************************************/ #include -#include #include #include #include #include -Q_DECLARE_METATYPE(QRegularExpression::PatternOptions) -Q_DECLARE_METATYPE(QRegularExpression::MatchType) -Q_DECLARE_METATYPE(QRegularExpression::MatchOptions) - -class tst_QRegularExpression : public QObject -{ - Q_OBJECT - -private slots: - void gettersSetters_data(); - void gettersSetters(); - void escape_data(); - void escape(); - void validity_data(); - void validity(); - void patternOptions_data(); - void patternOptions(); - void normalMatch_data(); - void normalMatch(); - void partialMatch_data(); - void partialMatch(); - void globalMatch_data(); - void globalMatch(); - void serialize_data(); - void serialize(); - void operatoreq_data(); - void operatoreq(); - void captureCount_data(); - void captureCount(); - -private: - void provideRegularExpressions(); -}; +#include "tst_qregularexpression.h" struct Match { @@ -1229,8 +1196,3 @@ void tst_QRegularExpression::captureCount() if (!re.isValid()) QCOMPARE(re.captureCount(), -1); } - -QTEST_APPLESS_MAIN(tst_QRegularExpression) - -#include "tst_qregularexpression.moc" - diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h new file mode 100644 index 0000000000..1a703a8f92 --- /dev/null +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Giuseppe D'Angelo . +** Contact: http://www.qt-project.org/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +Q_DECLARE_METATYPE(QRegularExpression::PatternOptions) +Q_DECLARE_METATYPE(QRegularExpression::MatchType) +Q_DECLARE_METATYPE(QRegularExpression::MatchOptions) + +class tst_QRegularExpression : public QObject +{ + Q_OBJECT + +private slots: + void gettersSetters_data(); + void gettersSetters(); + void escape_data(); + void escape(); + void validity_data(); + void validity(); + void patternOptions_data(); + void patternOptions(); + void normalMatch_data(); + void normalMatch(); + void partialMatch_data(); + void partialMatch(); + void globalMatch_data(); + void globalMatch(); + void serialize_data(); + void serialize(); + void operatoreq_data(); + void operatoreq(); + void captureCount_data(); + void captureCount(); + +private: + void provideRegularExpressions(); +}; -- cgit v1.2.3 From b7915a4d0d97a60fc30e55eb4cc1b10e7fe9ce2f Mon Sep 17 00:00:00 2001 From: Debao Zhang Date: Fri, 23 Dec 2011 00:27:32 +0800 Subject: Fix dockwidgets behavior when window resized or central widgets is set. When adding and showing a central widget in a QMainWindow then the layout does not respect the size policy of the central widget. This is a side effect of 059be19781a22d2e41f22072152589857d0fabf9 After the layout of QMainWindow is restored or the separator between central widget and dock widgets is moved by user, dock widgets should keep their size when the window if resized. Task-number: QTBUG-15689 Change-Id: Idfccb7b4ae057a99f431c2ed54e3b9fcfb6ef54c Reviewed-by: Friedemann Kleint --- src/widgets/widgets/qdockarealayout.cpp | 2 -- src/widgets/widgets/qdockarealayout_p.h | 2 +- src/widgets/widgets/qmainwindowlayout.cpp | 2 ++ tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp | 5 +++++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index a07ab73ad0..5adb2f1c95 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -2631,8 +2631,6 @@ void QDockAreaLayout::getGrid(QVector *_ver_struct_list, QSize bottom_max = docks[QInternal::BottomDock].maximumSize(); bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min); - fallbackToSizeHints = false; - if (_ver_struct_list != 0) { QVector &ver_struct_list = *_ver_struct_list; ver_struct_list.resize(3); diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h index 17078f3709..10eb0da651 100644 --- a/src/widgets/widgets/qdockarealayout_p.h +++ b/src/widgets/widgets/qdockarealayout_p.h @@ -232,7 +232,7 @@ public: QDockAreaLayout(QMainWindow *win); QDockAreaLayoutInfo docks[4]; int sep; // separator extent - bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the central widget is set) + bool fallbackToSizeHints; //determines if we should use the sizehint for the dock areas (true until the layout is restored or the separator is moved by user) mutable QVector separatorWidgets; bool isValid() const; diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index c67881e652..ff05503540 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -1351,6 +1351,8 @@ bool QMainWindowLayout::startSeparatorMove(const QPoint &pos) if (movingSeparator.isEmpty()) return false; + layoutState.dockAreaLayout.fallbackToSizeHints = false; + savedState = layoutState; movingSeparatorPos = movingSeparatorOrigin = pos; diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index 0f07546559..c6a039cb37 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -1435,6 +1435,11 @@ void MoveSeparator::apply(QMainWindow *mw) const } QVERIFY(!path.isEmpty()); + // For QTBUG-15689: + // Following commands is used to simulate user move action. A better way should + // use QMainWindowLayout::startSeparatorMove/separatorMove/endSeparatorMove, + // but then we will need real start/end position coordinates. + l->layoutState.dockAreaLayout.fallbackToSizeHints = false; l->layoutState.dockAreaLayout.separatorMove(path, QPoint(0, 0), QPoint(delta, delta)); } #endif -- cgit v1.2.3 From 3d19422ef16a230bb11dbbfe4a8cc9667f39bf15 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 6 Mar 2012 22:45:38 +0100 Subject: QtXml: make some constructors explicit This is a semi-automatic search, so I'm reasonably sure that all the exported ones have been caught. Change-Id: Ibb889038a583f419399cd044908d481413b2c48f Reviewed-by: Richard J. Moore --- src/xml/sax/qxml.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h index 86d0956290..038b0c750f 100644 --- a/src/xml/sax/qxml.h +++ b/src/xml/sax/qxml.h @@ -158,7 +158,7 @@ class Q_XML_EXPORT QXmlInputSource { public: QXmlInputSource(); - QXmlInputSource(QIODevice *dev); + explicit QXmlInputSource(QIODevice *dev); virtual ~QXmlInputSource(); virtual void setData(const QString& dat); -- cgit v1.2.3 From b319d44798fe4c5aa8b859966d64f28b08be28dd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 5 Mar 2012 14:42:42 +0100 Subject: QCursor: Associate cursor with screen. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduce cursor() accessor to QPlatformScreen. - Remove screen member of QPlatformCursor (a cursor can be shared by multiple screens of a virtual desktop). - Add QCursor::pos()/ QCursor::setPos() taking a QScreen-parameter, use primaryScreen() for old overloads. QCursor::pos() can then query the platform cursor for the position and return the position even if the mouse position is outside the windows owned by the Qt application. - Fix tests Reviewed-by: Samuel Rødal Task-number: QTBUG-22457 Task-number: QTBUG-22565 Task-number: QTBUG-20753 Change-Id: Ia69f37343f95772e934eab1cd806bd54cbdbbe51 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qcursor.cpp | 46 +++++++++++++++++++--- src/gui/kernel/qcursor.h | 4 ++ src/gui/kernel/qcursor_qpa.cpp | 40 +++++++++++-------- src/gui/kernel/qguiapplication.cpp | 22 ++++------- src/gui/kernel/qplatformcursor_qpa.cpp | 15 +++++-- src/gui/kernel/qplatformcursor_qpa.h | 10 ++--- src/gui/kernel/qplatformscreen_qpa.cpp | 11 ++++++ src/gui/kernel/qplatformscreen_qpa.h | 2 + src/plugins/platforms/cocoa/qcocoacursor.h | 2 +- src/plugins/platforms/cocoa/qcocoacursor.mm | 3 +- src/plugins/platforms/cocoa/qcocoaintegration.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 2 +- src/plugins/platforms/directfb/qdirectfbcursor.cpp | 4 +- src/plugins/platforms/directfb/qdirectfbcursor.h | 1 + src/plugins/platforms/directfb/qdirectfbscreen.h | 1 + src/plugins/platforms/kms/qkmscursor.cpp | 2 +- src/plugins/platforms/kms/qkmsscreen.cpp | 5 +++ src/plugins/platforms/kms/qkmsscreen.h | 1 + src/plugins/platforms/windows/qwindowscursor.cpp | 5 --- src/plugins/platforms/windows/qwindowscursor.h | 2 +- src/plugins/platforms/windows/qwindowsscreen.cpp | 10 ++++- src/plugins/platforms/windows/qwindowsscreen.h | 9 +++-- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- src/plugins/platforms/xcb/qxcbcursor.cpp | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 5 +++ src/plugins/platforms/xcb/qxcbscreen.h | 1 + src/plugins/platforms/xlib/qxlibcursor.cpp | 8 +--- src/plugins/platforms/xlib/qxlibcursor.h | 5 ++- src/plugins/platforms/xlib/qxlibscreen.cpp | 5 +++ src/plugins/platforms/xlib/qxlibscreen.h | 1 + src/widgets/kernel/qwidget_qpa.cpp | 14 +++---- .../qgraphicsview/tst_qgraphicsview.cpp | 13 ++++-- .../qgraphicswidget/tst_qgraphicswidget.cpp | 3 -- tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp | 6 --- 34 files changed, 167 insertions(+), 96 deletions(-) diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index f16e5c85de..95b2b4a28e 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -185,10 +185,10 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QPoint QCursor::pos() + \fn QPoint QCursor::pos(const QScreen *screen) - Returns the position of the cursor (hot spot) in global screen - coordinates. + Returns the position of the cursor (hot spot) of the \a screen + in global screen coordinates. You can call QWidget::mapFromGlobal() to translate it to widget coordinates. @@ -197,10 +197,23 @@ QT_BEGIN_NAMESPACE */ /*! - \fn void QCursor::setPos(int x, int y) + \fn QPoint QCursor::pos() + + Returns the position of the cursor (hot spot) of + the primary screen in global screen coordinates. + + You can call QWidget::mapFromGlobal() to translate it to widget + coordinates. + + \sa setPos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen() +*/ - Moves the cursor (hot spot) to the global screen position (\a x, - \a y). + +/*! + \fn void QCursor::setPos(QScreen *screen, int x, int y) + + Moves the cursor (hot spot) of the \a screen to the global + screen position (\a x, \a y). You can call QWidget::mapToGlobal() to translate widget coordinates to global screen coordinates. @@ -208,6 +221,18 @@ QT_BEGIN_NAMESPACE \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal() */ +/*! + \fn void QCursor::setPos(int x, int y) + + Moves the cursor (hot spot) of the primary screen + to the global screen position (\a x, \a y). + + You can call QWidget::mapToGlobal() to translate widget + coordinates to global screen coordinates. + + \sa pos(), QWidget::mapFromGlobal(), QWidget::mapToGlobal(), QGuiApplication::primaryScreen() +*/ + /*! \fn void QCursor::setPos (const QPoint &p) @@ -217,6 +242,15 @@ QT_BEGIN_NAMESPACE \a p. */ +/*! + \fn void QCursor::setPos (QScreen *screen,const QPoint &p) + + \overload + + Moves the cursor (hot spot) to the global screen position of the + \a screen at point \a p. +*/ + /***************************************************************************** QCursor stream functions *****************************************************************************/ diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index 00b709b308..4820bcee9b 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE class QVariant; +class QScreen; /* ### The fake cursor has to go first with old qdoc. @@ -101,8 +102,11 @@ public: QPoint hotSpot() const; static QPoint pos(); + static QPoint pos(const QScreen *screen); static void setPos(int x, int y); + static void setPos(QScreen *screen, int x, int y); inline static void setPos(const QPoint &p) { setPos(p.x(), p.y()); } + inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); } #ifdef qdoc HCURSOR_or_HANDLE handle() const; diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp index 7ba2e1c580..1c719c839e 100644 --- a/src/gui/kernel/qcursor_qpa.cpp +++ b/src/gui/kernel/qcursor_qpa.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include +#include #include #include #include @@ -110,27 +111,34 @@ void QCursorData::update() QPoint QCursor::pos() { + return QCursor::pos(QGuiApplication::primaryScreen()); +} + +QPoint QCursor::pos(const QScreen *screen) +{ + if (screen) + if (const QPlatformCursor *cursor = screen->handle()->cursor()) + return cursor->pos(); return QGuiApplicationPrivate::lastCursorPosition.toPoint(); } -void QCursor::setPos(int x, int y) +void QCursor::setPos(QScreen *screen, int x, int y) { - QPoint target(x, y); - - // Need to check, since some X servers generate null mouse move - // events, causing looping in applications which call setPos() on - // every mouse move event. - // - if (pos() == target) - return; - - QList > cursors = QPlatformCursorPrivate::getInstances(); - int cursorCount = cursors.count(); - for (int i = 0; i < cursorCount; ++i) { - const QWeakPointer &cursor(cursors.at(i)); - if (cursor) - cursor.data()->setPos(target); + if (screen) { + if (QPlatformCursor *cursor = screen->handle()->cursor()) { + const QPoint pos = QPoint(x, y); + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. + if (pos != cursor->pos()) + cursor->setPos(pos); + } } } +void QCursor::setPos(int x, int y) +{ + QCursor::setPos(QGuiApplication::primaryScreen(), x, y); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index f5aea654fc..42ce3745de 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -978,10 +978,9 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers); ev.setTimestamp(e->timestamp); #ifndef QT_NO_CURSOR - QList > cursors = QPlatformCursorPrivate::getInstances(); - for (int i = 0; i < cursors.count(); ++i) - if (cursors.at(i)) - cursors.at(i).data()->pointerEvent(ev); + if (const QScreen *screen = window->screen()) + if (QPlatformCursor *cursor = screen->handle()->cursor()) + cursor->pointerEvent(ev); #endif QGuiApplication::sendSpontaneousEvent(window, &ev); if (!e->synthetic && !ev.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) { @@ -1814,16 +1813,11 @@ void QGuiApplication::changeOverrideCursor(const QCursor &cursor) #ifndef QT_NO_CURSOR -static void applyCursor(QWindow *w, const QCursor &c) -{ - QCursor cc = c; - QList > cursors = QPlatformCursorPrivate::getInstances(); - int cursorCount = cursors.count(); - for (int i = 0; i < cursorCount; ++i) { - const QWeakPointer &cursor(cursors.at(i)); - if (cursor) - cursor.data()->changeCursor(&cc, w); - } +static inline void applyCursor(QWindow *w, QCursor c) +{ + if (const QScreen *screen = w->screen()) + if (QPlatformCursor *cursor = screen->handle()->cursor()) + cursor->changeCursor(&c, w); } static inline void applyCursor(const QList &l, const QCursor &c) diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp index fd7bcdcf18..a4e998ddbc 100644 --- a/src/gui/kernel/qplatformcursor_qpa.cpp +++ b/src/gui/kernel/qplatformcursor_qpa.cpp @@ -43,13 +43,22 @@ #include #include #include +#include +#include #include #include QT_BEGIN_NAMESPACE -QList > QPlatformCursorPrivate::instances; +QList QPlatformCursorPrivate::getInstances() +{ + QList result; + foreach (const QScreen *screen, QGuiApplicationPrivate::screen_list) + if (QPlatformCursor *cursor = screen->handle()->cursor()) + result.push_back(cursor); + return result; +} /*! \class QPlatformCursor @@ -93,10 +102,8 @@ QList > QPlatformCursorPrivate::instances; Constructs a QPlatformCursor for the given \a screen. */ -QPlatformCursor::QPlatformCursor(QPlatformScreen *scr ) - : screen(scr) +QPlatformCursor::QPlatformCursor() { - QPlatformCursorPrivate::instances.append(this); } QPoint QPlatformCursor::pos() const diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h index a8cbb282fa..e29cf87d03 100644 --- a/src/gui/kernel/qplatformcursor_qpa.h +++ b/src/gui/kernel/qplatformcursor_qpa.h @@ -74,13 +74,12 @@ class QPlatformCursor; class Q_GUI_EXPORT QPlatformCursorPrivate { public: - static QList > getInstances() { return instances; } - static QList > instances; + static QList getInstances(); }; class Q_GUI_EXPORT QPlatformCursor : public QObject { public: - QPlatformCursor(QPlatformScreen *); + QPlatformCursor(); // input methods virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); } @@ -88,11 +87,8 @@ public: virtual QPoint pos() const; virtual void setPos(const QPoint &pos); -protected: - QPlatformScreen* screen; // Where to request an update - private: - Q_DECLARE_PRIVATE(QPlatformCursor); + Q_DECLARE_PRIVATE(QPlatformCursor) friend void qt_qpa_set_cursor(QWidget * w, bool force); friend class QApplicationPrivate; }; diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp index c832d853f4..022f198073 100644 --- a/src/gui/kernel/qplatformscreen_qpa.cpp +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -41,6 +41,7 @@ #include "qplatformscreen_qpa.h" #include +#include #include #include #include @@ -250,4 +251,14 @@ QPlatformScreenPageFlipper *QPlatformScreen::pageFlipper() const return 0; } +/*! + Reimplement this function in subclass to return the cursor of the screen. + + The default implementation returns 0. +*/ +QPlatformCursor *QPlatformScreen::cursor() const +{ + return 0; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h index 7d74698074..b6eb91f9b2 100644 --- a/src/gui/kernel/qplatformscreen_qpa.h +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -63,6 +63,7 @@ class QPlatformBackingStore; class QPlatformOpenGLContext; class QPlatformScreenPrivate; class QPlatformWindow; +class QPlatformCursor; class QPlatformScreenPageFlipper; class QScreen; class QSurfaceFormat; @@ -103,6 +104,7 @@ public: virtual QString name() const { return QString(); } virtual QPlatformScreenPageFlipper *pageFlipper() const; + virtual QPlatformCursor *cursor() const; protected: QScopedPointer d_ptr; diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h index bccaa1e06b..85892ee820 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.h +++ b/src/plugins/platforms/cocoa/qcocoacursor.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QCocoaCursor : public QPlatformCursor { public: - explicit QCocoaCursor(QPlatformScreen *); + QCocoaCursor(); virtual void changeCursor(QCursor * widgetCursor, QWindow * widget); virtual QPoint pos() const; diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index bddfaa752e..56f0dcf72e 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -47,8 +47,7 @@ QT_BEGIN_NAMESPACE -QCocoaCursor::QCocoaCursor(QPlatformScreen *s) : - QPlatformCursor(s) +QCocoaCursor::QCocoaCursor() { // release cursors QHash::const_iterator i = m_cursors.constBegin(); diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index aa0c933fab..bf54915365 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -63,6 +63,7 @@ public: int depth() const { return m_depth; } QImage::Format format() const { return m_format; } QSizeF physicalSize() const { return m_physicalSize; } + QPlatformCursor *cursor() const { return m_cursor; } public: NSScreen *m_screen; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 7921cc6ae7..8411a795c1 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -79,7 +79,7 @@ QCocoaScreen::QCocoaScreen(int screenIndex) const qreal inch = 25.4; m_physicalSize = QSizeF(m_geometry.size()) * inch / dpi; - m_cursor = new QCocoaCursor(this); + m_cursor = new QCocoaCursor; }; QCocoaScreen::~QCocoaScreen() diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp index e1660a998a..a63bc48133 100644 --- a/src/plugins/platforms/directfb/qdirectfbcursor.cpp +++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE QDirectFBCursor::QDirectFBCursor(QPlatformScreen *screen) - : QPlatformCursor(screen) + : m_screen(screen) { m_image.reset(new QPlatformCursorImage(0, 0, 0, 0, 0, 0)); } @@ -70,7 +70,7 @@ void QDirectFBCursor::changeCursor(QCursor *cursor, QWindow *) } DFBResult res; - IDirectFBDisplayLayer *layer = toDfbLayer(screen); + IDirectFBDisplayLayer *layer = toDfbLayer(m_screen); IDirectFBSurface* surface(QDirectFbConvenience::dfbSurfaceForPlatformPixmap(map.handle())); res = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE); diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.h b/src/plugins/platforms/directfb/qdirectfbcursor.h index 3cc2825b28..f28e225dc7 100644 --- a/src/plugins/platforms/directfb/qdirectfbcursor.h +++ b/src/plugins/platforms/directfb/qdirectfbcursor.h @@ -60,6 +60,7 @@ public: private: QScopedPointer m_image; + QPlatformScreen *m_screen; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbscreen.h b/src/plugins/platforms/directfb/qdirectfbscreen.h index ad80576c8f..8535239088 100644 --- a/src/plugins/platforms/directfb/qdirectfbscreen.h +++ b/src/plugins/platforms/directfb/qdirectfbscreen.h @@ -61,6 +61,7 @@ public: int depth() const { return m_depth; } QImage::Format format() const { return m_format; } QSizeF physicalSize() const { return m_physicalSize; } + QPlatformCursor *cursor() const { return m_cursor.data(); } // DirectFb helpers IDirectFBDisplayLayer *dfbLayer() const; diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp index a38f66bd02..37817af39d 100644 --- a/src/plugins/platforms/kms/qkmscursor.cpp +++ b/src/plugins/platforms/kms/qkmscursor.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE QKmsCursor::QKmsCursor(QKmsScreen *screen) - : QPlatformCursor(screen), m_screen(screen), + : m_screen(screen), m_graphicsBufferManager(screen->device()->gbmDevice()) { gbm_bo *bo = gbm_bo_create(m_graphicsBufferManager, 64, 64, diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp index f1b9baf120..76b9bce28f 100644 --- a/src/plugins/platforms/kms/qkmsscreen.cpp +++ b/src/plugins/platforms/kms/qkmsscreen.cpp @@ -96,6 +96,11 @@ QSizeF QKmsScreen::physicalSize() const return m_physicalSize; } +QPlatformCursor *QKmsScreen::cursor() const +{ + return m_cursor; +} + GLuint QKmsScreen::framebufferObject() const { return m_bufferManager.framebufferObject(); diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h index 4cb547b424..058314a515 100644 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -61,6 +61,7 @@ public: int depth() const; QImage::Format format() const; QSizeF physicalSize() const; + QPlatformCursor *cursor() const; GLuint framebufferObject() const; quint32 crtcId() const { return m_crtcId; } diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index f75cbeb078..337ba9ab27 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -72,11 +72,6 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \sa QWindowsWindowCursor */ -QWindowsCursor::QWindowsCursor(QPlatformScreen *s) : - QPlatformCursor(s) -{ -} - HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY) { HCURSOR cur = 0; diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index a03c77a3b6..61c43dc4d2 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -70,7 +70,7 @@ private: class QWindowsCursor : public QPlatformCursor { public: - explicit QWindowsCursor(QPlatformScreen *); + QWindowsCursor() {} virtual void changeCursor(QCursor * widgetCursor, QWindow * widget); virtual QPoint pos() const { return mousePosition(); } diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 1dc5175515..2476e15169 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -147,6 +147,14 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) return dbg; } +// Return the cursor to be shared by all screens (virtual desktop). +static inline QSharedPointer sharedCursor() +{ + if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) + return static_cast(primaryScreen->handle())->windowsCursor(); + return QSharedPointer(new QWindowsCursor); +} + /*! \class QWindowsScreen \brief Windows screen. @@ -155,7 +163,7 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) */ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : - m_data(data), m_cursor(this) + m_data(data), m_cursor(sharedCursor()) { } diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 77a327a62a..5b9a50b2ab 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -46,6 +46,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -74,6 +75,8 @@ struct QWindowsScreenData class QWindowsScreen : public QPlatformScreen { public: + typedef QSharedPointer WindowsCursorPtr; + explicit QWindowsScreen(const QWindowsScreenData &data); static QWindowsScreen *screenOf(const QWindow *w = 0); @@ -98,14 +101,14 @@ public: inline void handleChanges(const QWindowsScreenData &newData); - const QWindowsCursor &cursor() const { return m_cursor; } - QWindowsCursor &cursor() { return m_cursor; } + QPlatformCursor *cursor() const { return m_cursor.data(); } + const WindowsCursorPtr &windowsCursor() const { return m_cursor; } const QWindowsScreenData &data() const { return m_data; } private: QWindowsScreenData m_data; - QWindowsCursor m_cursor; + const WindowsCursorPtr m_cursor; }; class QWindowsScreenManager diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f5cac4d4f0..1edb243f4e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -618,7 +618,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : m_windowState(aWindow->windowState()), m_opacity(1.0), m_mouseGrab(false), - m_cursor(QWindowsScreen::screenOf(aWindow)->cursor().standardWindowCursor()), + m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()), m_dropTarget(0), m_savedStyle(0) { diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index ed7c22b1e6..7e1b66829a 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -261,7 +261,7 @@ static const char * const cursorNames[] = { }; QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen) - : QXcbObject(conn), QPlatformCursor(screen), m_screen(screen) + : QXcbObject(conn), m_screen(screen) { if (cursorCount++) return; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 15ffc5b8ff..8b66ef4603 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -237,6 +237,11 @@ QSizeF QXcbScreen::physicalSize() const return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters); } +QPlatformCursor *QXcbScreen::cursor() const +{ + return m_cursor; +} + int QXcbScreen::screenNumber() const { return m_number; diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 870d4d5662..ac4ecb1c8d 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -68,6 +68,7 @@ public: int depth() const; QImage::Format format() const; QSizeF physicalSize() const; + QPlatformCursor *cursor() const; int screenNumber() const; diff --git a/src/plugins/platforms/xlib/qxlibcursor.cpp b/src/plugins/platforms/xlib/qxlibcursor.cpp index 8ab40e31ef..a714f82371 100644 --- a/src/plugins/platforms/xlib/qxlibcursor.cpp +++ b/src/plugins/platforms/xlib/qxlibcursor.cpp @@ -52,8 +52,7 @@ QT_BEGIN_NAMESPACE -QXlibCursor::QXlibCursor(QXlibScreen *screen) - : QPlatformCursor(screen) +QXlibCursor::QXlibCursor(QXlibScreen *screen) : m_screen(screen) { } @@ -191,9 +190,4 @@ Cursor QXlibCursor::createCursorShape(int cshape) return cursor; } -QXlibScreen * QXlibCursor::testLiteScreen() const -{ - return static_cast(screen); -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibcursor.h b/src/plugins/platforms/xlib/qxlibcursor.h index 92e42ac7a1..0056aa9554 100644 --- a/src/plugins/platforms/xlib/qxlibcursor.h +++ b/src/plugins/platforms/xlib/qxlibcursor.h @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -class QXlibCursor : QPlatformCursor +class QXlibCursor : public QPlatformCursor { public: QXlibCursor(QXlibScreen *screen); @@ -59,8 +59,9 @@ private: Cursor createCursorBitmap(QCursor * cursor); Cursor createCursorShape(int cshape); - QXlibScreen *testLiteScreen() const; + QXlibScreen *testLiteScreen() const { return m_screen; } QMap cursorMap; + QXlibScreen *m_screen; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp index fc903708b3..62c80b6ad4 100644 --- a/src/plugins/platforms/xlib/qxlibscreen.cpp +++ b/src/plugins/platforms/xlib/qxlibscreen.cpp @@ -241,6 +241,11 @@ QXlibScreen::~QXlibScreen() delete mDisplay; } +QPlatformCursor *QXlibScreen::cursor() const +{ + return mCursor; +} + Window QXlibScreen::rootWindow() { return RootWindow(mDisplay->nativeDisplay(), mScreen); diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h index c6672c3540..5bb6cc7735 100644 --- a/src/plugins/platforms/xlib/qxlibscreen.h +++ b/src/plugins/platforms/xlib/qxlibscreen.h @@ -63,6 +63,7 @@ public: int depth() const { return mDepth; } QImage::Format format() const { return mFormat; } QSizeF physicalSize() const { return mPhysicalSize; } + QPlatformCursor *cursor() const; Window rootWindow(); unsigned long blackPixel(); diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index a37de8547a..3d23b04ddf 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -905,16 +905,12 @@ void QWidgetPrivate::setModal_sys() } #ifndef QT_NO_CURSOR -static void applyCursor(QWidget *w, const QCursor &c) +static inline void applyCursor(QWidget *w, QCursor c) { - QCursor cc = c; - QList > cursors = QPlatformCursorPrivate::getInstances(); - int cursorCount = cursors.count(); - for (int i = 0; i < cursorCount; ++i) { - const QWeakPointer &cursor(cursors.at(i)); - if (cursor) - cursor.data()->changeCursor(&cc, w->window()->windowHandle()); - } + if (QWindow *window = w->windowHandle()) + if (const QScreen *screen = window->screen()) + if (QPlatformCursor *cursor = screen->handle()->cursor()) + cursor->changeCursor(&c, window); } void qt_qpa_set_cursor(QWidget *w, bool force) diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index af76b1c3c1..ee7ec7ba57 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -4338,9 +4338,16 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins() QPointF newMouseScenePos = view.mapToScene(mouseViewPos); qreal slack = 1; - QEXPECT_FAIL("", "QTBUG-22455", Abort); - QVERIFY(qAbs(newMouseScenePos.x() - mouseScenePos.x()) < slack); - QVERIFY(qAbs(newMouseScenePos.y() - mouseScenePos.y()) < slack); + + const qreal dx = qAbs(newMouseScenePos.x() - mouseScenePos.x()); + const qreal dy = qAbs(newMouseScenePos.y() - mouseScenePos.y()); + const QByteArray message = QString::fromLatin1("QTBUG-22455, distance: dx=%1, dy=%2 slack=%3 (%4)."). + arg(dx).arg(dy).arg(slack).arg(qApp->style()->metaObject()->className()).toLocal8Bit(); + // This is highly unstable (observed to pass on Windows and some Linux configurations). +#ifdef Q_OS_MAC + QEXPECT_FAIL("", message.constData(), Abort); +#endif + QVERIFY2(dx < slack && dy < slack, message.constData()); #endif } diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp index 0a2d0cd2f8..c6b2b49d98 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp @@ -1158,9 +1158,6 @@ void tst_QGraphicsWidget::initStyleOption() QCOMPARE(hasFocus, focus); bool isUnderMouse = option.state & QStyle::State_MouseOver; #ifndef Q_OS_WINCE -# if !defined(Q_OS_MAC) && !defined(Q_OS_WIN) - QEXPECT_FAIL("all", "QTBUG-22457", Abort); -# endif QCOMPARE(isUnderMouse, underMouse); #endif // if (layoutDirection != Qt::LeftToRight) diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 4fffd74491..473c5e05ec 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -562,9 +562,6 @@ void tst_QMenu::tearOff() QTest::mouseClick(menu, Qt::LeftButton, 0, QPoint(3, 3), 10); QTest::qWait(100); -#ifndef Q_OS_MAC - QEXPECT_FAIL("", "QTBUG-22565", Abort); -#endif QVERIFY(menu->isTearOffMenuVisible()); QPointer torn = 0; foreach (QWidget *w, QApplication::allWidgets()) { @@ -783,9 +780,6 @@ void tst_QMenu::task258920_mouseBorder() #ifdef Q_OS_WINCE_WM QSKIP("Mouse move related signals for Windows Mobile unavailable"); #endif - // ### fixme: Check platforms - QSKIP("QTBUG-20753 QCursor::setPos() / QTest::mouseMove() doesn't work on qpa"); - Menu258920 menu; // For styles which inherit from QWindowsStyle, styleHint(QStyle::SH_Menu_MouseTracking) is true. menu.setMouseTracking(true); -- cgit v1.2.3 From 6c612c933803ef57ea45e907d0181b40659148ac Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 7 Mar 2012 13:31:04 +0100 Subject: move postProcessProject() call to sane location there is totally no reason to call it unless the project is actually used for makefile generation, and the excessive calls actually mess up things. Change-Id: Idb7912a5404f6054010d2f29cce820a167de4f6f Reviewed-by: Marius Storm-Olsen --- qmake/generators/metamakefile.cpp | 4 ++++ qmake/project.cpp | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 39dd4ab797..b855585500 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -447,6 +447,8 @@ QT_END_INCLUDE_NAMESPACE MakefileGenerator * MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO) { + Option::postProcessProject(proj); + MakefileGenerator *mkfile = NULL; if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) { mkfile = new ProjectGenerator; @@ -492,6 +494,8 @@ MetaMakefileGenerator::createMakefileGenerator(QMakeProject *proj, bool noIO) MetaMakefileGenerator * MetaMakefileGenerator::createMetaGenerator(QMakeProject *proj, const QString &name, bool op, bool *success) { + Option::postProcessProject(proj); + MetaMakefileGenerator *ret = 0; if ((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || Option::qmake_mode == Option::QMAKE_GENERATE_PRL)) { diff --git a/qmake/project.cpp b/qmake/project.cpp index a9e99e4b79..7655f05f2e 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1386,7 +1386,6 @@ QMakeProject::read(uchar cmd) break; } } - Option::postProcessProject(this); // let Option post-process return true; } -- cgit v1.2.3